-
Notifications
You must be signed in to change notification settings - Fork 40
Description
Bug Description
Syntax highlighting is lost when a DiffView component is unmounted and then remounted with the same file content. The first render shows correct syntax highlighting, but subsequent renders show plain text without any highlight classes.
Steps to Reproduce
- Render a
DiffViewwithdiffViewHighlightenabled and aregisterHighlighter(e.g., lowlight) - Unmount the component (e.g., navigate away)
- Remount the component with the same diff data
- Expected: Syntax highlighting appears as on the first render
- Actual: No syntax highlighting — all code is plain text
Root Cause
The issue is in the syntax initialization effect across all framework packages (React, Vue, Svelte, Solid).
When DiffView remounts, the following sequence occurs:
useMemocreates a newDiffFileinstanceinitRaw()calls#doFile()→getFile(), which returns a cachedFilefrom the global_cacheMap. This cachedFilecarrieshighlighterNameandhighlighterTypefrom the first render.initRaw()→#syncSyntax()copies these values to the newDiffFile- The syntax effect checks:
if ( registerHighlighter.name !== diffFile._getHighlighterName() || registerHighlighter.type !== diffFile._getHighlighterType() || registerHighlighter.type !== "class" )
- Since
#syncSyntaxalready copied"lowlight"and"class"from the cachedFile, all three conditions arefalse initSyntax()is never called, leaving#newFileSyntaxLinesand#oldFileSyntaxLinesasnull- The diff renders with
diff-line-content-raw(plain text) instead ofdiff-line-syntax-raw(highlighted)
DOM Evidence
First render (working):
<span class="diff-line-syntax-raw">
<span class="hljs-keyword">class</span>
<span class="hljs-title class_">CherryPickInput</span>
...
</span>Second render (broken):
<span class="diff-line-content-raw">
<span data-template="true">class CherryPickInput(BaseModel):</span>
</span>Suggested Fix
The effect's guard condition is too aggressive. initSyntax() is already idempotent — when syntax is already initialized with a matching highlighter, it efficiently re-syncs syntax line references without recomputing. The effect should always call initSyntax() when highlighting is enabled, rather than trying to skip it based on highlighter metadata that may have been inherited from the global File cache.
Affected files:
packages/react/src/components/DiffView.tsxpackages/vue/src/components/DiffView.tsxpackages/svelte/src/lib/components/DiffView.sveltepackages/solid/src/components/DiffView.tsx