@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
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
// `stringOrHastToString` is already part of the always-loaded `useCode` shell
|
|
3
|
+
// (via `useCopyFunctionality`/`Pre`). Passing it into the lazy editing engine
|
|
4
|
+
// keeps that engine chunk from statically pulling it (and `hastDecompress`).
|
|
2
5
|
import { stringOrHastToString } from "../pipeline/hastUtils/index.mjs";
|
|
6
|
+
import { useCodeContext } from "../CodeProvider/CodeContext.mjs";
|
|
7
|
+
import { peekEditingEngine, loadEditingEngine, preloadEditingEngine, resetEditingEngineCache } from "./editingEngineCache.mjs";
|
|
8
|
+
// The edit-time runtime (`analyzeSource`/`shiftComments`/`toControlledCode`) lives
|
|
9
|
+
// in the shared `./EditingEngine` chunk — the SAME chunk `useEditable` loads, so
|
|
10
|
+
// they download together. The shell warms it as soon as a block is editable (the
|
|
11
|
+
// effect below); by the time the user can type — which itself waits on the
|
|
12
|
+
// editable engine — the engine is ready and `setSource` runs synchronously. A
|
|
13
|
+
// read-only block never loads it.
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Warms the editing engine so the next edit applies synchronously. Back-compat
|
|
17
|
+
* alias for {@link preloadEditingEngine}; the cache is shared with `useEditable`.
|
|
18
|
+
*/
|
|
19
|
+
export const preloadSourceEditingEngine = preloadEditingEngine;
|
|
20
|
+
|
|
21
|
+
/** Clears the shared editing-engine cache. Back-compat alias; for tests. */
|
|
22
|
+
export const resetSourceEditingEngineCache = resetEditingEngineCache;
|
|
3
23
|
|
|
4
24
|
/**
|
|
5
25
|
* Internal `setSource` shape used by the editing pipeline. The 3rd and 4th
|
|
@@ -9,254 +29,6 @@ import { stringOrHastToString } from "../pipeline/hastUtils/index.mjs";
|
|
|
9
29
|
* `(source, fileName?) => void`.
|
|
10
30
|
*/
|
|
11
31
|
|
|
12
|
-
/**
|
|
13
|
-
* Counts the number of lines in a string and records which 1-indexed lines are
|
|
14
|
-
* empty/whitespace-only, in a single pass, without allocating a line array.
|
|
15
|
-
* `emptyLines` is omitted when no blank lines were found to keep the common
|
|
16
|
-
* case allocation-free.
|
|
17
|
-
*/
|
|
18
|
-
function analyzeSource(source) {
|
|
19
|
-
let totalLines = 1;
|
|
20
|
-
let emptyLines;
|
|
21
|
-
let lineStart = 0;
|
|
22
|
-
const len = source.length;
|
|
23
|
-
for (let i = 0; i <= len; i += 1) {
|
|
24
|
-
if (i === len || source.charCodeAt(i) === 0x0a /* \n */) {
|
|
25
|
-
let isEmpty = true;
|
|
26
|
-
for (let j = lineStart; j < i; j += 1) {
|
|
27
|
-
const ch = source.charCodeAt(j);
|
|
28
|
-
// 0x20=space, 0x09=tab, 0x0D=CR, 0x0B=VT, 0x0C=FF
|
|
29
|
-
if (ch !== 0x20 && ch !== 0x09 && ch !== 0x0d && ch !== 0x0b && ch !== 0x0c) {
|
|
30
|
-
isEmpty = false;
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
if (isEmpty) {
|
|
35
|
-
if (!emptyLines) {
|
|
36
|
-
emptyLines = [];
|
|
37
|
-
}
|
|
38
|
-
emptyLines.push(totalLines);
|
|
39
|
-
}
|
|
40
|
-
if (i < len) {
|
|
41
|
-
totalLines += 1;
|
|
42
|
-
lineStart = i + 1;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return emptyLines ? {
|
|
47
|
-
totalLines,
|
|
48
|
-
emptyLines
|
|
49
|
-
} : {
|
|
50
|
-
totalLines
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Shifts 1-indexed comment line numbers after a source edit.
|
|
56
|
-
* Accepts a precomputed `lineDelta` (positive = lines added, negative = lines deleted)
|
|
57
|
-
* and the cursor `position` (0-indexed in the new text) to determine which
|
|
58
|
-
* comments move and by how much.
|
|
59
|
-
*
|
|
60
|
-
* When lines are deleted, comments from the deleted range are collapsed
|
|
61
|
-
* onto the edit line and recorded in a collapseMap so they can be restored
|
|
62
|
-
* if the deletion is undone (lines re-added at the same position).
|
|
63
|
-
*
|
|
64
|
-
* Empty/whitespace-only deleted lines are special: since they had no real
|
|
65
|
-
* content that "shifted upward" into editLine, their comments are pushed
|
|
66
|
-
* to editLine + 1 (like `-end` boundary markers) so the highlighted region
|
|
67
|
-
* shrinks instead of shifting onto the previous line.
|
|
68
|
-
*/
|
|
69
|
-
function shiftComments(comments, lineDelta, position, existingCollapseMap, oldEmptyLines) {
|
|
70
|
-
if (!comments || Object.keys(comments).length === 0) {
|
|
71
|
-
return {
|
|
72
|
-
comments,
|
|
73
|
-
collapseMap: existingCollapseMap
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
if (lineDelta === 0) {
|
|
77
|
-
return {
|
|
78
|
-
comments,
|
|
79
|
-
collapseMap: existingCollapseMap
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// position.line is 0-indexed in the new text.
|
|
84
|
-
// lineDelta is positive for insertions and negative for deletions.
|
|
85
|
-
// Convert to the 1-indexed line in old text that the cursor was on:
|
|
86
|
-
// For additions (lineDelta > 0):
|
|
87
|
-
// - Forward typing: position is the POST-edit cursor (extent === 0).
|
|
88
|
-
// Cursor moved down by lineDelta, so old line = position.line - lineDelta.
|
|
89
|
-
// - Undo of a multi-line delete: the saved position has extent > 0 and
|
|
90
|
-
// points to the SELECTION-START in the redone text — i.e. where the
|
|
91
|
-
// re-inserted lines begin. The "edit line" is that line itself; the
|
|
92
|
-
// new lines come AFTER it.
|
|
93
|
-
// For deletions (lineDelta < 0): cursor stayed where it was, old line = position.line.
|
|
94
|
-
const isUndoOfMultiLineDelete = lineDelta > 0 && position.extent > 0;
|
|
95
|
-
const editLine = isUndoOfMultiLineDelete ? position.line + 1 : position.line - Math.max(0, lineDelta) + 1; // 1-indexed
|
|
96
|
-
|
|
97
|
-
const shifted = {};
|
|
98
|
-
let collapseMap = existingCollapseMap ? {
|
|
99
|
-
...existingCollapseMap
|
|
100
|
-
} : {};
|
|
101
|
-
const newCollapsed = [];
|
|
102
|
-
|
|
103
|
-
// Build a list of comment strings to exclude from the edit line after restore.
|
|
104
|
-
// Uses an array (not Set) to correctly handle duplicate comment strings
|
|
105
|
-
// across separate collapsed entries.
|
|
106
|
-
let restoredComments;
|
|
107
|
-
|
|
108
|
-
// On expansion, check if we can restore previously collapsed comments
|
|
109
|
-
if (lineDelta > 0 && collapseMap[editLine]) {
|
|
110
|
-
const entries = collapseMap[editLine];
|
|
111
|
-
const restored = [];
|
|
112
|
-
const remaining = [];
|
|
113
|
-
for (const entry of entries) {
|
|
114
|
-
if (entry.offset <= lineDelta) {
|
|
115
|
-
restored.push(entry);
|
|
116
|
-
} else {
|
|
117
|
-
remaining.push(entry);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Place restored comments at their original offsets from the edit line
|
|
122
|
-
restoredComments = [];
|
|
123
|
-
for (const entry of restored) {
|
|
124
|
-
const restoredLine = editLine + entry.offset;
|
|
125
|
-
shifted[restoredLine] = [...(shifted[restoredLine] ?? []), ...entry.comments];
|
|
126
|
-
restoredComments.push(...entry.comments);
|
|
127
|
-
}
|
|
128
|
-
if (remaining.length > 0) {
|
|
129
|
-
collapseMap[editLine] = remaining;
|
|
130
|
-
} else {
|
|
131
|
-
delete collapseMap[editLine];
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// O(1) lookup against the precomputed empty-line set from the old source.
|
|
136
|
-
const oldEmptyLineSet = oldEmptyLines && oldEmptyLines.length > 0 ? new Set(oldEmptyLines) : undefined;
|
|
137
|
-
for (const [lineStr, commentArr] of Object.entries(comments)) {
|
|
138
|
-
const line = Number(lineStr);
|
|
139
|
-
if (line <= editLine) {
|
|
140
|
-
// Before or at the edit line — unchanged.
|
|
141
|
-
// If this is the edit line and we restored comments from it, filter them out.
|
|
142
|
-
let arr = commentArr;
|
|
143
|
-
if (line === editLine && restoredComments) {
|
|
144
|
-
const remaining = [...commentArr];
|
|
145
|
-
for (const c of restoredComments) {
|
|
146
|
-
const idx = remaining.indexOf(c);
|
|
147
|
-
if (idx !== -1) {
|
|
148
|
-
remaining.splice(idx, 1);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
arr = remaining;
|
|
152
|
-
}
|
|
153
|
-
if (arr.length > 0) {
|
|
154
|
-
shifted[line] = [...(shifted[line] ?? []), ...arr];
|
|
155
|
-
}
|
|
156
|
-
} else if (lineDelta < 0 && line <= editLine - lineDelta) {
|
|
157
|
-
// Within the deleted range — collapse comments onto the edit line.
|
|
158
|
-
// Boundary comments (ending with '-end') go to editLine + 1 instead,
|
|
159
|
-
// so range-end markers stay at the first line after the highlighted range.
|
|
160
|
-
// Boundary comments are NOT tracked in collapseMap — they shift normally
|
|
161
|
-
// on subsequent edits so the range naturally expands/contracts.
|
|
162
|
-
//
|
|
163
|
-
// Empty/whitespace-only deleted lines also push their regular comments
|
|
164
|
-
// to editLine + 1: nothing actually shifted upward into editLine, so the
|
|
165
|
-
// highlighted region should shrink rather than expand onto the line above.
|
|
166
|
-
const wasEmptyLine = oldEmptyLineSet?.has(line) ?? false;
|
|
167
|
-
const regular = commentArr.filter(c => !c.endsWith('-end'));
|
|
168
|
-
const boundary = commentArr.filter(c => c.endsWith('-end'));
|
|
169
|
-
if (regular.length > 0) {
|
|
170
|
-
if (wasEmptyLine) {
|
|
171
|
-
const target = editLine + 1;
|
|
172
|
-
shifted[target] = [...(shifted[target] ?? []), ...regular];
|
|
173
|
-
} else {
|
|
174
|
-
shifted[editLine] = [...(shifted[editLine] ?? []), ...regular];
|
|
175
|
-
newCollapsed.push({
|
|
176
|
-
offset: line - editLine,
|
|
177
|
-
comments: regular
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
if (boundary.length > 0) {
|
|
182
|
-
const boundaryTarget = editLine + 1;
|
|
183
|
-
shifted[boundaryTarget] = [...(shifted[boundaryTarget] ?? []), ...boundary];
|
|
184
|
-
}
|
|
185
|
-
} else {
|
|
186
|
-
// After the edit — shift
|
|
187
|
-
const newLine = line + lineDelta;
|
|
188
|
-
shifted[newLine] = [...(shifted[newLine] ?? []), ...commentArr];
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Also shift existing collapse map entries that are after the edit line
|
|
193
|
-
const shiftedCollapseMap = {};
|
|
194
|
-
for (const [lineStr, entries] of Object.entries(collapseMap)) {
|
|
195
|
-
const line = Number(lineStr);
|
|
196
|
-
if (line <= editLine) {
|
|
197
|
-
shiftedCollapseMap[line] = entries;
|
|
198
|
-
} else {
|
|
199
|
-
shiftedCollapseMap[line + lineDelta] = entries;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
collapseMap = shiftedCollapseMap;
|
|
203
|
-
if (newCollapsed.length > 0) {
|
|
204
|
-
collapseMap[editLine] = [...(collapseMap[editLine] ?? []), ...newCollapsed];
|
|
205
|
-
}
|
|
206
|
-
const finalCollapseMap = Object.keys(collapseMap).length > 0 ? collapseMap : undefined;
|
|
207
|
-
return {
|
|
208
|
-
comments: shifted,
|
|
209
|
-
collapseMap: finalCollapseMap
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Converts Code to ControlledCode, normalizing sources and extraFiles entries.
|
|
215
|
-
* VariantSource can be HAST nodes; ControlledCode requires plain strings.
|
|
216
|
-
* VariantExtraFiles allows plain string entries; ControlledVariantExtraFiles
|
|
217
|
-
* requires `{ source }` objects. Without this normalization, parseControlledCode
|
|
218
|
-
* reads `.source` on a string and gets `undefined`, dropping file content.
|
|
219
|
-
*/
|
|
220
|
-
function toControlledCode(code) {
|
|
221
|
-
const result = {};
|
|
222
|
-
for (const [key, variant] of Object.entries(code)) {
|
|
223
|
-
if (!variant || typeof variant === 'string') {
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
const source = variant.source != null ? stringOrHastToString(variant.source) : variant.source;
|
|
227
|
-
let extraFiles;
|
|
228
|
-
if (variant.extraFiles) {
|
|
229
|
-
extraFiles = {};
|
|
230
|
-
for (const [fileName, entry] of Object.entries(variant.extraFiles)) {
|
|
231
|
-
if (typeof entry === 'string') {
|
|
232
|
-
extraFiles[fileName] = {
|
|
233
|
-
source: entry,
|
|
234
|
-
...analyzeSource(entry)
|
|
235
|
-
};
|
|
236
|
-
} else {
|
|
237
|
-
const extraSource = entry.source != null ? stringOrHastToString(entry.source) : null;
|
|
238
|
-
extraFiles[fileName] = {
|
|
239
|
-
source: extraSource,
|
|
240
|
-
...(entry.comments ? {
|
|
241
|
-
comments: entry.comments
|
|
242
|
-
} : {}),
|
|
243
|
-
...(extraSource != null ? analyzeSource(extraSource) : {})
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
result[key] = {
|
|
249
|
-
...variant,
|
|
250
|
-
source,
|
|
251
|
-
...(source != null ? analyzeSource(source) : {}),
|
|
252
|
-
...(extraFiles ? {
|
|
253
|
-
extraFiles
|
|
254
|
-
} : {})
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
return result;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
32
|
/**
|
|
261
33
|
* Hook for managing source code editing functionality.
|
|
262
34
|
*
|
|
@@ -272,12 +44,28 @@ export function useSourceEditing({
|
|
|
272
44
|
disabled
|
|
273
45
|
}) {
|
|
274
46
|
const contextSetCode = context?.setCode;
|
|
47
|
+
// The provider's editing-engine loader (shared with `useEditable`); dedupes the
|
|
48
|
+
// chunk fetch page-wide. Undefined without a provider → the built-in default.
|
|
49
|
+
const {
|
|
50
|
+
editingEngineLoader
|
|
51
|
+
} = useCodeContext();
|
|
52
|
+
|
|
53
|
+
// Monotonic token bumped by every `setSource`/`reset`. A cold first edit
|
|
54
|
+
// defers its commit into a microtask; if a later edit or a `reset` happens
|
|
55
|
+
// before the engine resolves, the stale deferred commit must NOT run (it would
|
|
56
|
+
// re-apply a superseded edit and, after a reset, reverse it). The deferred
|
|
57
|
+
// callback captures the token at schedule time and bails if it changed.
|
|
58
|
+
const editTokenRef = React.useRef(0);
|
|
275
59
|
const setSource = React.useCallback((source, fileName, position, preParsed) => {
|
|
276
60
|
if (!contextSetCode) {
|
|
277
61
|
console.warn('setCode is not available in the current context. Ensure you are using CodeControllerContext.');
|
|
278
62
|
return;
|
|
279
63
|
}
|
|
280
64
|
|
|
65
|
+
// Mark this edit as the latest; a deferred (cold) commit checks this.
|
|
66
|
+
editTokenRef.current += 1;
|
|
67
|
+
const editToken = editTokenRef.current;
|
|
68
|
+
|
|
281
69
|
// Stash any pre-computed parse result against the resolved file name
|
|
282
70
|
// BEFORE the controlled-code update commits, so that the synchronous
|
|
283
71
|
// `parseControlledCode` pass triggered by the resulting React render
|
|
@@ -293,80 +81,136 @@ export function useSourceEditing({
|
|
|
293
81
|
hast: preParsed
|
|
294
82
|
});
|
|
295
83
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
const effectiveFileName = fileName ?? selectedVariant?.fileName;
|
|
305
|
-
const isMainFile = effectiveFileName === selectedVariant?.fileName;
|
|
306
|
-
if (isMainFile) {
|
|
307
|
-
if (source === variant.source) {
|
|
308
|
-
return currentCode ?? newCode;
|
|
84
|
+
const applyUpdate = engine => {
|
|
85
|
+
contextSetCode(currentCode => {
|
|
86
|
+
const newCode = currentCode ? {
|
|
87
|
+
...currentCode
|
|
88
|
+
} : engine.toControlledCode(effectiveCode, selectedVariantKey, context?.fallbacks, stringOrHastToString);
|
|
89
|
+
const variant = newCode[selectedVariantKey];
|
|
90
|
+
if (!variant) {
|
|
91
|
+
return newCode;
|
|
309
92
|
}
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
source
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
} = analyzeSource(source);
|
|
339
|
-
const oldLineCount = extraEntry?.totalLines ?? (extraEntry?.source != null ? analyzeSource(extraEntry.source).totalLines : 0);
|
|
340
|
-
const {
|
|
341
|
-
comments: shiftedComments,
|
|
342
|
-
collapseMap: newCollapseMap
|
|
343
|
-
} = position ? shiftComments(extraEntry?.comments, newLineCount - oldLineCount, position, extraEntry?.collapseMap, extraEntry?.emptyLines) : {
|
|
344
|
-
comments: undefined,
|
|
345
|
-
collapseMap: undefined
|
|
346
|
-
};
|
|
347
|
-
newCode[selectedVariantKey] = {
|
|
348
|
-
...variant,
|
|
349
|
-
extraFiles: {
|
|
350
|
-
...variant.extraFiles,
|
|
351
|
-
[effectiveFileName]: {
|
|
352
|
-
...extraEntry,
|
|
353
|
-
source,
|
|
354
|
-
totalLines: newLineCount,
|
|
355
|
-
emptyLines: newEmptyLines,
|
|
356
|
-
comments: shiftedComments,
|
|
357
|
-
collapseMap: newCollapseMap
|
|
358
|
-
}
|
|
93
|
+
const effectiveFileName = fileName ?? selectedVariant?.fileName;
|
|
94
|
+
const isMainFile = effectiveFileName === selectedVariant?.fileName;
|
|
95
|
+
|
|
96
|
+
// Recompute the edited file's comment/window state for `source`.
|
|
97
|
+
// `shiftComments` shifts the comment map by the line delta relative to
|
|
98
|
+
// the edit position; on undo/redo the `position.history` flag tells it
|
|
99
|
+
// to reverse the edit (re-inserting deleted lines after the pre-edit
|
|
100
|
+
// caret), and its `collapseMap` restores comments that a deletion
|
|
101
|
+
// collapsed — so undo/redo is reversed from existing state, with no
|
|
102
|
+
// per-edit snapshots kept. `entry` is the file being edited (main
|
|
103
|
+
// variant or an extra file); both expose the same
|
|
104
|
+
// source/comments/collapseMap/totalLines/emptyLines shape.
|
|
105
|
+
const deriveFileState = (entry, nextSource) => {
|
|
106
|
+
// `analyzeSource` ignores a single trailing newline, so the host
|
|
107
|
+
// source (often unterminated) and the live contentEditable text
|
|
108
|
+
// (always terminated) report consistent line counts — the delta is
|
|
109
|
+
// 0 when no line was actually added or removed.
|
|
110
|
+
const {
|
|
111
|
+
totalLines,
|
|
112
|
+
emptyLines
|
|
113
|
+
} = engine.analyzeSource(nextSource);
|
|
114
|
+
if (!position) {
|
|
115
|
+
return {
|
|
116
|
+
comments: undefined,
|
|
117
|
+
collapseMap: undefined,
|
|
118
|
+
totalLines,
|
|
119
|
+
emptyLines
|
|
120
|
+
};
|
|
359
121
|
}
|
|
122
|
+
const oldLineCount = entry?.totalLines ?? (entry?.source != null ? engine.analyzeSource(entry.source).totalLines : 0);
|
|
123
|
+
const {
|
|
124
|
+
comments,
|
|
125
|
+
collapseMap
|
|
126
|
+
} = engine.shiftComments(entry?.comments, totalLines - oldLineCount, position, entry?.collapseMap, entry?.emptyLines);
|
|
127
|
+
return {
|
|
128
|
+
comments,
|
|
129
|
+
collapseMap,
|
|
130
|
+
totalLines,
|
|
131
|
+
emptyLines
|
|
132
|
+
};
|
|
360
133
|
};
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
134
|
+
if (isMainFile) {
|
|
135
|
+
if (source === variant.source) {
|
|
136
|
+
return currentCode ?? newCode;
|
|
137
|
+
}
|
|
138
|
+
const {
|
|
139
|
+
totalLines,
|
|
140
|
+
emptyLines,
|
|
141
|
+
comments,
|
|
142
|
+
collapseMap
|
|
143
|
+
} = deriveFileState(variant, source);
|
|
144
|
+
newCode[selectedVariantKey] = {
|
|
145
|
+
...variant,
|
|
146
|
+
source,
|
|
147
|
+
totalLines,
|
|
148
|
+
emptyLines,
|
|
149
|
+
comments,
|
|
150
|
+
collapseMap
|
|
151
|
+
};
|
|
152
|
+
} else if (effectiveFileName) {
|
|
153
|
+
const extraEntry = variant.extraFiles?.[effectiveFileName];
|
|
154
|
+
if (source === extraEntry?.source) {
|
|
155
|
+
return currentCode ?? newCode;
|
|
156
|
+
}
|
|
157
|
+
const {
|
|
158
|
+
totalLines,
|
|
159
|
+
emptyLines,
|
|
160
|
+
comments,
|
|
161
|
+
collapseMap
|
|
162
|
+
} = deriveFileState(extraEntry, source);
|
|
163
|
+
newCode[selectedVariantKey] = {
|
|
164
|
+
...variant,
|
|
165
|
+
extraFiles: {
|
|
166
|
+
...variant.extraFiles,
|
|
167
|
+
[effectiveFileName]: {
|
|
168
|
+
...extraEntry,
|
|
169
|
+
source,
|
|
170
|
+
totalLines,
|
|
171
|
+
emptyLines,
|
|
172
|
+
comments,
|
|
173
|
+
collapseMap
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return newCode;
|
|
179
|
+
});
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// Apply synchronously from the warm cache (the common case — the warm
|
|
183
|
+
// effect below loads the engine as soon as the block is editable). On a
|
|
184
|
+
// cold first edit, defer this one update until the chunk resolves; later
|
|
185
|
+
// edits are synchronous.
|
|
186
|
+
const warmEngine = peekEditingEngine();
|
|
187
|
+
if (warmEngine) {
|
|
188
|
+
applyUpdate(warmEngine);
|
|
189
|
+
} else {
|
|
190
|
+
Promise.resolve(loadEditingEngine(editingEngineLoader)).then(loaded => {
|
|
191
|
+
// Bail if a later edit or a reset superseded this one while loading.
|
|
192
|
+
if (editTokenRef.current === editToken) {
|
|
193
|
+
applyUpdate(loaded);
|
|
194
|
+
}
|
|
195
|
+
}).catch(() => {});
|
|
196
|
+
}
|
|
197
|
+
}, [contextSetCode, selectedVariantKey, effectiveCode, selectedVariant, context?.preParsedCache, context?.fallbacks, editingEngineLoader]);
|
|
198
|
+
|
|
199
|
+
// Warm the edit-time runtime as soon as the block is editable, so the first
|
|
200
|
+
// edit applies synchronously (no flash). Read-only blocks never load it.
|
|
201
|
+
React.useEffect(() => {
|
|
202
|
+
if (peekEditingEngine() || !contextSetCode || disabled) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
preloadEditingEngine(editingEngineLoader).catch(() => {});
|
|
206
|
+
}, [contextSetCode, disabled, editingEngineLoader]);
|
|
365
207
|
const reset = React.useCallback(() => {
|
|
366
208
|
if (!contextSetCode) {
|
|
367
209
|
console.warn('setCode is not available in the current context. Ensure you are using CodeControllerContext.');
|
|
368
210
|
return;
|
|
369
211
|
}
|
|
212
|
+
// Supersede any pending cold edit so it can't re-apply after this reset.
|
|
213
|
+
editTokenRef.current += 1;
|
|
370
214
|
contextSetCode(undefined);
|
|
371
215
|
}, [contextSetCode]);
|
|
372
216
|
const isEditable = !disabled && Boolean(contextSetCode) && Boolean(selectedVariant);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SourceEnhancers, SourceComments, VariantSource } from "../CodeHighlighter/types.mjs";
|
|
2
|
+
import type { FallbackNode } from "../CodeHighlighter/fallbackFormat.mjs";
|
|
2
3
|
export interface UseSourceEnhancingProps {
|
|
3
4
|
/** The source to enhance (from transformed files or variant) */
|
|
4
5
|
source: VariantSource | null | undefined;
|
|
@@ -8,6 +9,8 @@ export interface UseSourceEnhancingProps {
|
|
|
8
9
|
comments: SourceComments | undefined;
|
|
9
10
|
/** Array of enhancer functions to apply */
|
|
10
11
|
sourceEnhancers?: SourceEnhancers;
|
|
12
|
+
/** Fallback data for deriving the DEFLATE decompression dictionary */
|
|
13
|
+
fallback?: FallbackNode[];
|
|
11
14
|
}
|
|
12
15
|
export interface UseSourceEnhancingResult {
|
|
13
16
|
/** The enhanced source */
|
|
@@ -19,5 +22,6 @@ export declare function useSourceEnhancing({
|
|
|
19
22
|
source,
|
|
20
23
|
fileName,
|
|
21
24
|
comments,
|
|
22
|
-
sourceEnhancers
|
|
25
|
+
sourceEnhancers,
|
|
26
|
+
fallback
|
|
23
27
|
}: UseSourceEnhancingProps): UseSourceEnhancingResult;
|
|
@@ -1,44 +1,29 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import * as React from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { decodeHastSource } from "../pipeline/loadIsomorphicCodeVariant/decodeHastSource.mjs";
|
|
5
5
|
import { recordEnhancerApplied, shouldSkipEnhancer } from "../pipeline/loadIsomorphicCodeVariant/runSourceEnhancers.mjs";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
* Used to determine if the source can be enhanced.
|
|
10
|
-
*/
|
|
11
|
-
function isHastRoot(source) {
|
|
12
|
-
if (typeof source !== 'object' || source === null) {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
return 'type' in source && source.type === 'root';
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Resolves a VariantSource to a HastRoot if possible.
|
|
20
|
-
* Handles decompression of compressed HAST and parsing of JSON HAST.
|
|
8
|
+
* Resolves a `VariantSource` to a HAST root that is safe to mutate.
|
|
21
9
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
10
|
+
* Uses the shared `decodeHastSource` cache to amortize decompression and
|
|
11
|
+
* `JSON.parse` across other consumers (`Pre`, `useFileNavigation`,
|
|
12
|
+
* `sourceLineCounts`), then `structuredClone`s the result because the
|
|
13
|
+
* enhancer pipeline mutates `root.data` via `recordEnhancerApplied`.
|
|
14
|
+
* Returns `null` for string or unrecognized sources.
|
|
15
|
+
*
|
|
16
|
+
* The variant `fallback` is forwarded to `decodeHastSource` so the compressed
|
|
17
|
+
* payload is decompressed with the matching DEFLATE dictionary and each frame's
|
|
18
|
+
* `data.fallback` is restored — enhancers then keep that per-frame fallback in
|
|
19
|
+
* sync as they mutate the tree.
|
|
24
20
|
*/
|
|
25
|
-
function resolveHastRoot(source) {
|
|
26
|
-
if (!source) {
|
|
21
|
+
function resolveHastRoot(source, fallback) {
|
|
22
|
+
if (!source || typeof source === 'string') {
|
|
27
23
|
return null;
|
|
28
24
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
if ('hastJson' in source) {
|
|
33
|
-
return JSON.parse(source.hastJson);
|
|
34
|
-
}
|
|
35
|
-
if ('hastCompressed' in source) {
|
|
36
|
-
return JSON.parse(decompressHast(source.hastCompressed));
|
|
37
|
-
}
|
|
38
|
-
if (isHastRoot(source)) {
|
|
39
|
-
return source;
|
|
40
|
-
}
|
|
41
|
-
return null;
|
|
25
|
+
const cached = decodeHastSource(source, fallback);
|
|
26
|
+
return cached ? structuredClone(cached) : null;
|
|
42
27
|
}
|
|
43
28
|
|
|
44
29
|
/**
|
|
@@ -138,14 +123,14 @@ function applyEnhancersUntilAsync(source, comments, fileName, enhancers) {
|
|
|
138
123
|
* Enhancers are run in order; sync ones apply immediately, and the first
|
|
139
124
|
* async enhancer's promise is captured so it can be continued in an effect.
|
|
140
125
|
*/
|
|
141
|
-
function computeEnhanceState(source, comments, fileName, sourceEnhancers) {
|
|
126
|
+
function computeEnhanceState(source, comments, fileName, sourceEnhancers, fallback) {
|
|
142
127
|
if (!source || !sourceEnhancers || sourceEnhancers.length === 0) {
|
|
143
128
|
return {
|
|
144
129
|
enhancedSource: source ?? null,
|
|
145
130
|
asyncWork: null
|
|
146
131
|
};
|
|
147
132
|
}
|
|
148
|
-
const resolved = resolveHastRoot(source);
|
|
133
|
+
const resolved = resolveHastRoot(source, fallback);
|
|
149
134
|
if (!resolved) {
|
|
150
135
|
return {
|
|
151
136
|
enhancedSource: source ?? null,
|
|
@@ -169,14 +154,15 @@ export function useSourceEnhancing({
|
|
|
169
154
|
source,
|
|
170
155
|
fileName,
|
|
171
156
|
comments,
|
|
172
|
-
sourceEnhancers
|
|
157
|
+
sourceEnhancers,
|
|
158
|
+
fallback
|
|
173
159
|
}) {
|
|
174
160
|
// Track previous values to detect changes
|
|
175
161
|
const [prevSource, setPrevSource] = React.useState(source);
|
|
176
162
|
const [prevEnhancers, setPrevEnhancers] = React.useState(sourceEnhancers);
|
|
177
163
|
const [prevComments, setPrevComments] = React.useState(comments);
|
|
178
164
|
const [prevFileName, setPrevFileName] = React.useState(fileName);
|
|
179
|
-
const [state, setState] = React.useState(() => computeEnhanceState(source, comments, fileName, sourceEnhancers));
|
|
165
|
+
const [state, setState] = React.useState(() => computeEnhanceState(source, comments, fileName, sourceEnhancers, fallback));
|
|
180
166
|
const hasChanged = source !== prevSource || sourceEnhancers !== prevEnhancers || comments !== prevComments || fileName !== prevFileName;
|
|
181
167
|
|
|
182
168
|
// When inputs change, apply sync enhancers immediately during render
|
|
@@ -193,7 +179,7 @@ export function useSourceEnhancing({
|
|
|
193
179
|
if (fileName !== prevFileName) {
|
|
194
180
|
setPrevFileName(fileName);
|
|
195
181
|
}
|
|
196
|
-
setState(computeEnhanceState(source, comments, fileName, sourceEnhancers));
|
|
182
|
+
setState(computeEnhanceState(source, comments, fileName, sourceEnhancers, fallback));
|
|
197
183
|
}
|
|
198
184
|
|
|
199
185
|
// Continue from the first async enhancer without re-running sync ones
|