Repository navigation
Fix variant transforms and highlight gating - #4
Merged
Merged
Conversation
- Keep fallbacks per variant (`variantFallbacks`) so a file decodes with its own dictionary when variants share file names; the transform and source-editing engines prefer a file's own fallback - Scope the context's `availableTransforms` to the variant it was computed for, and latch the stored transform once highlighting settles - Gate `deferHighlight` on transforms in any variant, and render with `deferHighlightRender` so code stays highlighted while the deltas of a re-parse are computed (`getPendingTransformedCode`, line deltas on highlighted sources) - Render files a transform passes through with their original dictionary (`isPassThroughFile`) - Keep full fallbacks inline for `fallbackCollapsed` blocks that have no residual blob - Add e2e fixtures for switching variants with a transform applied Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Resolve the useCode/user.spec.ts conflict with the copy feedback tests by keeping both: the variant blocks first, then 'copy feedback'. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes decoding, transforms and highlighting when a block has several variants. Found while building
@fairgarden/design's code block on@fairgarden/docs.HAST dictionary mismatchin production under the TS → JS transform.main.deferHighlightwaits whenever any variant has transforms. Rendering gets its own narrower gate, so code stays highlighted, and current, while deltas compute.Per-variant dictionaries
Cause.
useCodechooses the variant it renders, but the context's fallbacks belonged to the highlighter's initial variant, looked up by file name alone. After a switch, a same-named file was decoded with the wrong dictionary, the transform threw, and the TS source stayed on screen. Only production payloads are compressed, which is why this never showed in dev.highlightAfter: 'init'without aContentLoadingfailed the same way.Fix:
variantFallbacks(variant → file name → dictionary), built byresolveVariantFallbacksincodeToFallbackProps.ts.useCodepasses the rendered variant's dictionaries to its sub-hooks.TransformEngineandSourceEditingEngineprefer a file's ownfallbackover the map.styles.csswhile TS → JS is active) keep their fallback, line counts and language (isPassThroughFile). Before, a block that mounted with the transform already on crashed with "Failed to decode the source HAST payload".fallbackCollapsedrenders on the client. With no compressed residual,prepareInitialSourceputs the full fallbacks on the client code. Before,<Pre>hit a dictionary mismatch.Transforms follow the rendered variant
availableTransformsVariant).useTransformManagementreuses that list only for that variant, and otherwise derives one from the rendered variant's code. This holds whethervariantis controlled, uncontrolled, or driven by a controller. Before, a variant without transforms could show the JS toggle.useVariantSelectionuses), so a re-parse no longer drops an applied transform.Highlight gating
deferHighlightwaits for deltas whenever any variant has transforms (hasAnyVariantTransforms, next togetAvailableTransforms). Before, it checked only the highlighter's own variant. So in a block whose first variant has no transforms, switching to a TypeScript variant and toggling JS could commit before the deltas landed, then re-flow a frame later. Blocks with no transforms anywhere still skip the wait, and all-transform blocks are unchanged.holdGate, the variant bootstrap, transform toggles andswapInFlightall use this gate.deferHighlightRender). Before,useCodealso useddeferHighlightfor rendering. So on a re-parse (a newcodeprop,refresh(), a lazily loaded variant) a block dropped to plain text, and showed the previous code, stale if it had changed.getPendingTransformedCode:applyCodeTransformWithCommentsnow applies a text-level delta to an already-highlighted source. Before, it threw "Transform failed" and showed TS under a.jsxname.Tests
CodeHighlighterClient.deferHighlight.test.tsxholds the deltas computation by hand. It covers the mixed-variant reproduction and guard cases for commit gating (4), plus rendering during a re-parse (5; the first-load markup is pinned unchanged).resolveVariantFallbacks,getPendingTransformedCode,hasAnyVariantTransforms,isPassThroughFile,applyCodeTransformline deltas,prepareInitialSourcewithout a residual, and compressed sources inTransformEngine,SourceEditingEngine(new file),toControlledCode,useFileNavigation,useTransformManagementanduseCode.CodeHighlighter/user.spec.tsx: transforms per rendered variant, and keeping a transform across same-named files. The transform test now clears localStorage, so it doesn't depend on test order.createCompressedFileinpipeline/hastUtils/hastCompression.testUtils.tsreplaces three copies of the same fixture (not exported).demo-variants-transform/(variants sharing a file name) reproduced the mismatch on a production build before the fix.demo-variants-mixed-transform/(one variant without transforms, one TypeScript) checks for re-flow.Verification
pnpm test --runpnpm typescript/pnpm eslint/ prettierpnpm docs:lib/pnpm docs:buildpnpm docs:validatelib/components/code-highlighter(production)demo-variantsis flaky onmaintoo, failing 30–60% of the time. The Tailwind option never appears after clicking the Select, which looks like a click before hydration.