@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.
Files changed (319) hide show
  1. package/ChunkProvider/ChunkContext.d.mts +10 -0
  2. package/ChunkProvider/ChunkContext.mjs +15 -0
  3. package/ChunkProvider/ChunkProvider.d.mts +14 -0
  4. package/ChunkProvider/ChunkProvider.mjs +38 -0
  5. package/ChunkProvider/PreloadContext.d.mts +14 -0
  6. package/ChunkProvider/PreloadContext.mjs +18 -0
  7. package/ChunkProvider/PreloadProvider.d.mts +13 -0
  8. package/ChunkProvider/PreloadProvider.mjs +33 -0
  9. package/ChunkProvider/index.d.mts +7 -0
  10. package/ChunkProvider/index.mjs +7 -0
  11. package/ChunkProvider/types.d.mts +23 -0
  12. package/ChunkProvider/types.mjs +1 -0
  13. package/ChunkProvider/usePreload.d.mts +8 -0
  14. package/ChunkProvider/usePreload.mjs +21 -0
  15. package/CodeControllerContext/CodeControllerContext.d.mts +11 -0
  16. package/CodeControllerContext/CodeControllerContext.mjs +2 -1
  17. package/CodeHighlighter/CodeHighlighter.d.mts +15 -1
  18. package/CodeHighlighter/CodeHighlighter.mjs +97 -319
  19. package/CodeHighlighter/CodeHighlighterChunk.d.mts +42 -0
  20. package/CodeHighlighter/CodeHighlighterChunk.mjs +77 -0
  21. package/CodeHighlighter/CodeHighlighterClient.mjs +597 -128
  22. package/CodeHighlighter/CodeHighlighterContext.d.mts +57 -1
  23. package/CodeHighlighter/CodeHighlighterFallbackContext.d.mts +14 -2
  24. package/CodeHighlighter/CodeHighlighterFallbackContext.mjs +1 -3
  25. package/CodeHighlighter/CodeInitialSourceLoader.d.mts +10 -0
  26. package/CodeHighlighter/CodeInitialSourceLoader.mjs +108 -0
  27. package/CodeHighlighter/CodeSourceLoader.d.mts +11 -0
  28. package/CodeHighlighter/CodeSourceLoader.mjs +128 -0
  29. package/CodeHighlighter/buildCodeHighlighterChunkProps.d.mts +47 -0
  30. package/CodeHighlighter/buildCodeHighlighterChunkProps.mjs +61 -0
  31. package/CodeHighlighter/buildStringFallback.d.mts +29 -0
  32. package/CodeHighlighter/buildStringFallback.mjs +42 -0
  33. package/CodeHighlighter/codeToFallbackProps.d.mts +31 -2
  34. package/CodeHighlighter/codeToFallbackProps.mjs +347 -42
  35. package/CodeHighlighter/createClientProps.d.mts +17 -0
  36. package/CodeHighlighter/createClientProps.mjs +78 -0
  37. package/CodeHighlighter/errors.d.mts +6 -0
  38. package/CodeHighlighter/errors.mjs +10 -0
  39. package/CodeHighlighter/fallbackCompression.d.mts +96 -0
  40. package/CodeHighlighter/fallbackCompression.mjs +253 -0
  41. package/CodeHighlighter/fallbackFormat.d.mts +137 -0
  42. package/CodeHighlighter/fallbackFormat.mjs +422 -0
  43. package/CodeHighlighter/index.d.mts +4 -1
  44. package/CodeHighlighter/index.mjs +3 -1
  45. package/CodeHighlighter/mergeComments.d.mts +38 -0
  46. package/CodeHighlighter/mergeComments.mjs +80 -0
  47. package/CodeHighlighter/prepareInitialSource.d.mts +42 -0
  48. package/CodeHighlighter/prepareInitialSource.mjs +292 -0
  49. package/CodeHighlighter/resolveFallbackCritical.d.mts +23 -0
  50. package/CodeHighlighter/resolveFallbackCritical.mjs +44 -0
  51. package/CodeHighlighter/types.d.mts +272 -8
  52. package/CodeHighlighter/useCodeFallback.d.mts +94 -0
  53. package/CodeHighlighter/useCodeFallback.mjs +204 -0
  54. package/CodeHighlighter/useGrammarsReady.d.mts +18 -0
  55. package/CodeHighlighter/useGrammarsReady.mjs +45 -0
  56. package/CodeHighlighter/useSpeculativeCodePreload.d.mts +26 -0
  57. package/CodeHighlighter/useSpeculativeCodePreload.mjs +40 -0
  58. package/CodeHighlighter/useSpeculativeEditingPreload.d.mts +33 -0
  59. package/CodeHighlighter/useSpeculativeEditingPreload.mjs +58 -0
  60. package/CodeHighlighter/useSpeculativeGrammarPreload.d.mts +23 -0
  61. package/CodeHighlighter/useSpeculativeGrammarPreload.mjs +31 -0
  62. package/CodeHighlighter/useSpeculativeUseCodePreload.d.mts +22 -0
  63. package/CodeHighlighter/useSpeculativeUseCodePreload.mjs +41 -0
  64. package/CodeProvider/CodeContext.d.mts +47 -12
  65. package/CodeProvider/CodeContext.mjs +7 -0
  66. package/CodeProvider/CodeProvider.d.mts +4 -2
  67. package/CodeProvider/CodeProvider.mjs +40 -102
  68. package/CodeProvider/CodeProviderLazy.d.mts +40 -0
  69. package/CodeProvider/CodeProviderLazy.mjs +96 -0
  70. package/CodeProvider/constants.d.mts +26 -0
  71. package/CodeProvider/constants.mjs +24 -0
  72. package/CodeProvider/createParseSourceWorkerClient.d.mts +6 -0
  73. package/CodeProvider/createParseSourceWorkerClient.mjs +22 -2
  74. package/CodeProvider/index.d.mts +2 -1
  75. package/CodeProvider/index.mjs +9 -1
  76. package/CodeProvider/parseSourceWorker.mjs +33 -0
  77. package/CodeProvider/useCodeProviderValue.d.mts +54 -0
  78. package/CodeProvider/useCodeProviderValue.mjs +188 -0
  79. package/CoordinatedLazy/ChunkServerLoader.d.mts +25 -0
  80. package/CoordinatedLazy/ChunkServerLoader.mjs +97 -0
  81. package/CoordinatedLazy/CoordinatedContentContext.d.mts +15 -0
  82. package/CoordinatedLazy/CoordinatedContentContext.mjs +22 -0
  83. package/CoordinatedLazy/CoordinatedFallbackContext.d.mts +11 -0
  84. package/CoordinatedLazy/CoordinatedFallbackContext.mjs +13 -0
  85. package/CoordinatedLazy/CoordinatedGateContext.d.mts +14 -0
  86. package/CoordinatedLazy/CoordinatedGateContext.mjs +19 -0
  87. package/CoordinatedLazy/CoordinatedLazy.d.mts +14 -0
  88. package/CoordinatedLazy/CoordinatedLazy.mjs +86 -0
  89. package/CoordinatedLazy/CoordinatedLazyClient.d.mts +24 -0
  90. package/CoordinatedLazy/CoordinatedLazyClient.mjs +65 -0
  91. package/CoordinatedLazy/LazyContent.d.mts +26 -0
  92. package/CoordinatedLazy/LazyContent.mjs +80 -0
  93. package/CoordinatedLazy/LazyContentServer.d.mts +18 -0
  94. package/CoordinatedLazy/LazyContentServer.mjs +25 -0
  95. package/CoordinatedLazy/buildChunkRenderInputs.d.mts +8 -0
  96. package/CoordinatedLazy/buildChunkRenderInputs.mjs +35 -0
  97. package/CoordinatedLazy/createCoordinatedLazy.d.mts +32 -0
  98. package/CoordinatedLazy/createCoordinatedLazy.mjs +127 -0
  99. package/CoordinatedLazy/index.d.mts +14 -0
  100. package/CoordinatedLazy/index.mjs +18 -0
  101. package/CoordinatedLazy/resolveChunkRender.d.mts +26 -0
  102. package/CoordinatedLazy/resolveChunkRender.mjs +73 -0
  103. package/CoordinatedLazy/types.d.mts +408 -0
  104. package/CoordinatedLazy/types.mjs +1 -0
  105. package/CoordinatedLazy/useChunk.d.mts +30 -0
  106. package/CoordinatedLazy/useChunk.mjs +135 -0
  107. package/CoordinatedLazy/useCoordinatedFallback.d.mts +12 -0
  108. package/CoordinatedLazy/useCoordinatedFallback.mjs +40 -0
  109. package/CoordinatedLazy/useCoordinatedSwap.d.mts +16 -0
  110. package/CoordinatedLazy/useCoordinatedSwap.mjs +124 -0
  111. package/LICENSE +1 -1
  112. package/abstractCreateDemo/abstractCreateDemo.d.mts +54 -3
  113. package/abstractCreateDemo/abstractCreateDemo.mjs +47 -7
  114. package/abstractCreateDemo/resolveDemoFlag.d.mts +20 -0
  115. package/abstractCreateDemo/resolveDemoFlag.mjs +25 -0
  116. package/abstractCreateStream/abstractCreateStream.d.mts +18 -0
  117. package/abstractCreateStream/abstractCreateStream.mjs +45 -0
  118. package/abstractCreateStream/index.d.mts +2 -0
  119. package/abstractCreateStream/index.mjs +1 -0
  120. package/abstractCreateStream/types.d.mts +34 -0
  121. package/abstractCreateStream/types.mjs +1 -0
  122. package/abstractCreateTypes/TypeCode.mjs +12 -11
  123. package/abstractCreateTypes/typesToJsx.mjs +30 -9
  124. package/cli/ensureDemoClients.mjs +4 -148
  125. package/cli/ensureDemoPages.d.mts +45 -0
  126. package/cli/ensureDemoPages.mjs +99 -0
  127. package/cli/fileUtils/index.d.mts +11 -0
  128. package/cli/fileUtils/index.mjs +48 -0
  129. package/cli/findDemoIndexFiles.d.mts +15 -0
  130. package/cli/findDemoIndexFiles.mjs +121 -0
  131. package/cli/index.mjs +1 -1
  132. package/cli/loadNextConfig.d.mts +25 -0
  133. package/cli/loadNextConfig.mjs +60 -1
  134. package/cli/runBrowser.mjs +1 -1
  135. package/cli/runValidate.mjs +44 -1
  136. package/package.json +84 -4
  137. package/pipeline/enhanceCodeEmphasis/enhanceCodeEmphasis.mjs +30 -0
  138. package/pipeline/enhanceCodeEmphasis/enhanceCodeEmphasisLazy.d.mts +17 -0
  139. package/pipeline/enhanceCodeEmphasis/enhanceCodeEmphasisLazy.mjs +52 -0
  140. package/pipeline/hastUtils/frameFallbackFromSpans.d.mts +18 -0
  141. package/pipeline/hastUtils/frameFallbackFromSpans.mjs +24 -0
  142. package/pipeline/hastUtils/hast.d.mts +27 -0
  143. package/pipeline/hastUtils/hastCompression.d.mts +3 -1
  144. package/pipeline/hastUtils/hastCompression.mjs +9 -1
  145. package/pipeline/hastUtils/hastDecompress.mjs +10 -4
  146. package/pipeline/hastUtils/hastDictionary.mjs +9 -0
  147. package/pipeline/hastUtils/hastUtils.d.mts +4 -3
  148. package/pipeline/hastUtils/hastUtils.mjs +24 -12
  149. package/pipeline/hastUtils/index.d.mts +2 -1
  150. package/pipeline/hastUtils/index.mjs +2 -1
  151. package/pipeline/hastUtils/stripHighlightingSpans.d.mts +6 -2
  152. package/pipeline/hastUtils/stripHighlightingSpans.mjs +22 -10
  153. package/pipeline/lintJavascriptDemoFocus/lintJavascriptDemoFocus.mjs +10 -7
  154. package/pipeline/loadIsomorphicCodeVariant/applyCodeTransform.d.mts +31 -13
  155. package/pipeline/loadIsomorphicCodeVariant/applyCodeTransform.mjs +50 -55
  156. package/pipeline/loadIsomorphicCodeVariant/applyCodeTransformWithComments.d.mts +78 -0
  157. package/pipeline/loadIsomorphicCodeVariant/applyCodeTransformWithComments.mjs +405 -0
  158. package/pipeline/loadIsomorphicCodeVariant/computeHastDeltas.d.mts +5 -5
  159. package/pipeline/loadIsomorphicCodeVariant/computeHastDeltas.mjs +36 -66
  160. package/pipeline/loadIsomorphicCodeVariant/decodeHastSource.d.mts +23 -0
  161. package/pipeline/loadIsomorphicCodeVariant/decodeHastSource.mjs +92 -0
  162. package/pipeline/loadIsomorphicCodeVariant/decodeSource.d.mts +19 -0
  163. package/pipeline/loadIsomorphicCodeVariant/decodeSource.mjs +25 -0
  164. package/pipeline/loadIsomorphicCodeVariant/decodeSourceToText.d.mts +17 -0
  165. package/pipeline/loadIsomorphicCodeVariant/decodeSourceToText.mjs +26 -0
  166. package/pipeline/loadIsomorphicCodeVariant/diffHast.d.mts +26 -2
  167. package/pipeline/loadIsomorphicCodeVariant/diffHast.mjs +563 -19
  168. package/pipeline/loadIsomorphicCodeVariant/embedTransforms.d.mts +49 -0
  169. package/pipeline/loadIsomorphicCodeVariant/embedTransforms.mjs +152 -0
  170. package/pipeline/loadIsomorphicCodeVariant/findExpandingRanges.d.mts +51 -0
  171. package/pipeline/loadIsomorphicCodeVariant/findExpandingRanges.mjs +161 -0
  172. package/pipeline/loadIsomorphicCodeVariant/flattenCodeVariant.mjs +6 -3
  173. package/pipeline/loadIsomorphicCodeVariant/getAvailableTransforms.d.mts +12 -0
  174. package/pipeline/loadIsomorphicCodeVariant/getAvailableTransforms.mjs +44 -0
  175. package/pipeline/loadIsomorphicCodeVariant/getInitialVisibleSourceLines.d.mts +16 -0
  176. package/pipeline/loadIsomorphicCodeVariant/getInitialVisibleSourceLines.mjs +74 -0
  177. package/pipeline/loadIsomorphicCodeVariant/loadCodeFallback.mjs +17 -5
  178. package/pipeline/loadIsomorphicCodeVariant/loadIsomorphicCodeVariant.mjs +229 -15
  179. package/pipeline/loadIsomorphicCodeVariant/transformSource.d.mts +2 -2
  180. package/pipeline/loadIsomorphicCodeVariant/transformSource.mjs +56 -22
  181. package/pipeline/loadPrecomputedCodeHighlighter/loadPrecomputedCodeHighlighter.d.mts +18 -0
  182. package/pipeline/loadPrecomputedCodeHighlighter/loadPrecomputedCodeHighlighter.mjs +11 -7
  183. package/pipeline/loadServerTypes/hastTypeUtils.d.mts +2 -2
  184. package/pipeline/loadServerTypes/hastTypeUtils.mjs +4 -4
  185. package/pipeline/loadServerTypes/loadServerTypes.mjs +1 -1
  186. package/pipeline/loadServerTypesMeta/extractJSDocText.d.mts +14 -0
  187. package/pipeline/loadServerTypesMeta/extractJSDocText.mjs +60 -0
  188. package/pipeline/loadServerTypesMeta/processTypes.mjs +43 -46
  189. package/pipeline/loadServerTypesText/order.mjs +1 -1
  190. package/pipeline/loadServerTypesText/parseTypesMarkdown.mjs +3 -1
  191. package/pipeline/loaderUtils/index.d.mts +0 -1
  192. package/pipeline/loaderUtils/index.mjs +0 -1
  193. package/pipeline/loaderUtils/parseImportsAndComments.d.mts +5 -1
  194. package/pipeline/loaderUtils/parseImportsAndComments.mjs +19 -9
  195. package/pipeline/loaderUtils/resolveModulePath.mjs +23 -1
  196. package/pipeline/parseCreateFactoryCall/parseCreateFactoryCall.d.mts +12 -0
  197. package/pipeline/parseCreateFactoryCall/parseCreateFactoryCall.mjs +17 -13
  198. package/pipeline/parseSource/addLineGutters.mjs +45 -11
  199. package/pipeline/parseSource/calculateFrameRanges.d.mts +22 -0
  200. package/pipeline/parseSource/calculateFrameRanges.mjs +69 -25
  201. package/pipeline/parseSource/detectGrammarScopes.d.mts +13 -0
  202. package/pipeline/parseSource/detectGrammarScopes.mjs +35 -0
  203. package/pipeline/parseSource/extendSyntaxTokens.mjs +501 -43
  204. package/pipeline/parseSource/frameVisibility.d.mts +47 -0
  205. package/pipeline/parseSource/frameVisibility.mjs +114 -0
  206. package/pipeline/parseSource/grammarCache.d.mts +33 -0
  207. package/pipeline/parseSource/grammarCache.mjs +73 -0
  208. package/pipeline/parseSource/grammarLoaders.d.mts +14 -0
  209. package/pipeline/parseSource/grammarLoaders.mjs +24 -0
  210. package/pipeline/parseSource/grammarMaps.d.mts +21 -1
  211. package/pipeline/parseSource/grammarMaps.mjs +36 -0
  212. package/pipeline/parseSource/isFrameSpan.d.mts +19 -0
  213. package/pipeline/parseSource/isFrameSpan.mjs +24 -0
  214. package/pipeline/parseSource/parseSource.d.mts +41 -6
  215. package/pipeline/parseSource/parseSource.mjs +184 -36
  216. package/pipeline/parseSource/redistributeFrameFallbacks.d.mts +40 -0
  217. package/pipeline/parseSource/redistributeFrameFallbacks.mjs +138 -0
  218. package/pipeline/parseSource/restructureFrames.d.mts +5 -0
  219. package/pipeline/parseSource/restructureFrames.mjs +179 -16
  220. package/pipeline/syncPageIndex/metadataToMarkdown.mjs +6 -2
  221. package/pipeline/transformHtmlCodeBlock/transformHtmlCodeBlock.d.mts +26 -0
  222. package/pipeline/transformHtmlCodeBlock/transformHtmlCodeBlock.mjs +181 -114
  223. package/pipeline/transformHtmlCodeInline/removeSuffixFromHighlightedNodes.d.mts +12 -0
  224. package/pipeline/transformHtmlCodeInline/removeSuffixFromHighlightedNodes.mjs +52 -0
  225. package/pipeline/transformHtmlCodeInline/transformHtmlCodeInline.mjs +22 -1
  226. package/pipeline/transformTypescriptToJavascript/removeTypes.d.mts +5 -8
  227. package/pipeline/transformTypescriptToJavascript/removeTypes.mjs +27 -93
  228. package/useCode/EditableEngine.d.mts +233 -0
  229. package/useCode/EditableEngine.mjs +1712 -0
  230. package/useCode/EditingEngine.d.mts +13 -0
  231. package/useCode/EditingEngine.mjs +14 -0
  232. package/useCode/Pre.browser.mjs +5 -1
  233. package/useCode/Pre.d.mts +127 -1
  234. package/useCode/Pre.mjs +417 -165
  235. package/useCode/SourceEditingEngine.d.mts +50 -0
  236. package/useCode/SourceEditingEngine.mjs +461 -0
  237. package/useCode/TransformEngine.d.mts +39 -0
  238. package/useCode/TransformEngine.mjs +208 -0
  239. package/useCode/editingEngineCache.d.mts +29 -0
  240. package/useCode/editingEngineCache.mjs +68 -0
  241. package/useCode/sourceLineCounts.d.mts +80 -0
  242. package/useCode/sourceLineCounts.mjs +284 -0
  243. package/useCode/subscribeToggleNudge.d.mts +3 -0
  244. package/useCode/subscribeToggleNudge.mjs +95 -0
  245. package/useCode/transformEngineCache.d.mts +21 -0
  246. package/useCode/transformEngineCache.mjs +60 -0
  247. package/useCode/useCode.d.mts +140 -1
  248. package/useCode/useCode.mjs +250 -19
  249. package/useCode/useCodeUtils.d.mts +131 -20
  250. package/useCode/useCodeUtils.mjs +267 -194
  251. package/useCode/useCopyFunctionality.d.mts +13 -1
  252. package/useCode/useCopyFunctionality.mjs +39 -9
  253. package/useCode/useEditable.browser.mjs +10 -2
  254. package/useCode/useEditable.d.mts +27 -106
  255. package/useCode/useEditable.integration.browser.d.mts +1 -0
  256. package/useCode/useEditable.integration.browser.mjs +870 -0
  257. package/useCode/useEditable.mjs +198 -1247
  258. package/useCode/useEditableUtils.d.mts +50 -1
  259. package/useCode/useEditableUtils.mjs +29 -0
  260. package/useCode/useFileNavigation.d.mts +91 -3
  261. package/useCode/useFileNavigation.mjs +201 -41
  262. package/useCode/useHighlightGate.d.mts +17 -0
  263. package/useCode/useHighlightGate.mjs +147 -0
  264. package/useCode/useSourceEditing.d.mts +8 -0
  265. package/useCode/useSourceEditing.mjs +158 -314
  266. package/useCode/useSourceEnhancing.d.mts +5 -1
  267. package/useCode/useSourceEnhancing.mjs +22 -36
  268. package/useCode/useTransformManagement.d.mts +93 -5
  269. package/useCode/useTransformManagement.mjs +496 -28
  270. package/useCode/useTransitionPhase.d.mts +24 -0
  271. package/useCode/useTransitionPhase.mjs +49 -0
  272. package/useCode/useUIState.d.mts +2 -2
  273. package/useCode/useUIState.mjs +8 -8
  274. package/useCode/useVariantSelection.d.mts +130 -6
  275. package/useCode/useVariantSelection.mjs +529 -93
  276. package/useCodeWindow/useCodeWindow.d.mts +19 -2
  277. package/useCodeWindow/useCodeWindow.mjs +98 -71
  278. package/useCoordinated/coordinatePreference.d.mts +439 -0
  279. package/useCoordinated/coordinatePreference.mjs +951 -0
  280. package/useCoordinated/coordinatePreference.testUtils.d.mts +21 -0
  281. package/useCoordinated/coordinatePreference.testUtils.mjs +69 -0
  282. package/useCoordinated/createSettleGate.d.mts +96 -0
  283. package/useCoordinated/createSettleGate.mjs +171 -0
  284. package/useCoordinated/index.d.mts +8 -0
  285. package/useCoordinated/index.mjs +8 -0
  286. package/useCoordinated/layoutShiftGate.d.mts +24 -0
  287. package/useCoordinated/layoutShiftGate.mjs +79 -0
  288. package/useCoordinated/pageSettleGate.d.mts +11 -0
  289. package/useCoordinated/pageSettleGate.mjs +13 -0
  290. package/useCoordinated/scheduleTasks.d.mts +23 -0
  291. package/useCoordinated/scheduleTasks.mjs +45 -0
  292. package/useCoordinated/useCoordinated.d.mts +193 -0
  293. package/useCoordinated/useCoordinated.mjs +469 -0
  294. package/useCoordinated/useCoordinatedLazy.d.mts +17 -0
  295. package/useCoordinated/useCoordinatedLazy.mjs +38 -0
  296. package/useCoordinated/useCoordinatedLocalStorage.d.mts +16 -0
  297. package/useCoordinated/useCoordinatedLocalStorage.mjs +22 -0
  298. package/useCoordinated/useCoordinatedPreference.d.mts +20 -0
  299. package/useCoordinated/useCoordinatedPreference.mjs +26 -0
  300. package/useCoordinated/useSettleGate.d.mts +11 -0
  301. package/useCoordinated/useSettleGate.mjs +34 -0
  302. package/useDemo/exportVariant.d.mts +12 -5
  303. package/useDemo/exportVariant.mjs +59 -5
  304. package/useDemo/useDemo.d.mts +5 -2
  305. package/useScrollAnchor/useScrollAnchor.mjs +28 -5
  306. package/useStream/index.d.mts +6 -0
  307. package/useStream/index.mjs +6 -0
  308. package/useStream/streamChunks.d.mts +23 -0
  309. package/useStream/streamChunks.mjs +85 -0
  310. package/useStream/types.d.mts +45 -0
  311. package/useStream/types.mjs +1 -0
  312. package/useStream/useStream.d.mts +57 -0
  313. package/useStream/useStream.mjs +119 -0
  314. package/useStream/useStreamController.d.mts +15 -0
  315. package/useStream/useStreamController.mjs +90 -0
  316. package/withDocsInfra/withDocsInfra.d.mts +19 -0
  317. package/withDocsInfra/withDocsInfra.mjs +13 -5
  318. package/pipeline/loaderUtils/convertCommentsToOneIndexed.d.mts +0 -8
  319. 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
- contextSetCode(currentCode => {
297
- const newCode = currentCode ? {
298
- ...currentCode
299
- } : toControlledCode(effectiveCode);
300
- const variant = newCode[selectedVariantKey];
301
- if (!variant) {
302
- return newCode;
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
- totalLines: newLineCount,
312
- emptyLines: newEmptyLines
313
- } = analyzeSource(source);
314
- const oldLineCount = variant.totalLines ?? (variant.source != null ? analyzeSource(variant.source).totalLines : 0);
315
- const {
316
- comments: shiftedComments,
317
- collapseMap: newCollapseMap
318
- } = position ? shiftComments(variant.comments, newLineCount - oldLineCount, position, variant.collapseMap, variant.emptyLines) : {
319
- comments: undefined,
320
- collapseMap: undefined
321
- };
322
- newCode[selectedVariantKey] = {
323
- ...variant,
324
- source,
325
- totalLines: newLineCount,
326
- emptyLines: newEmptyLines,
327
- comments: shiftedComments,
328
- collapseMap: newCollapseMap
329
- };
330
- } else if (effectiveFileName) {
331
- const extraEntry = variant.extraFiles?.[effectiveFileName];
332
- if (source === extraEntry?.source) {
333
- return currentCode ?? newCode;
334
- }
335
- const {
336
- totalLines: newLineCount,
337
- emptyLines: newEmptyLines
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
- return newCode;
363
- });
364
- }, [contextSetCode, selectedVariantKey, effectiveCode, selectedVariant, context?.preParsedCache]);
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 { decompressHast } from "../pipeline/hastUtils/index.mjs";
4
+ import { decodeHastSource } from "../pipeline/loadIsomorphicCodeVariant/decodeHastSource.mjs";
5
5
  import { recordEnhancerApplied, shouldSkipEnhancer } from "../pipeline/loadIsomorphicCodeVariant/runSourceEnhancers.mjs";
6
6
 
7
7
  /**
8
- * Type guard to check if a source value is a HAST root node.
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
- * @param source - The source to resolve (can be HAST, hastJson, hastCompressed, or string)
23
- * @returns The resolved HastRoot or null if the source cannot be resolved
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
- if (typeof source === 'string') {
30
- return null; // String sources need parsing first
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