fix(CodeHighlighter): load Prism grammars through a bundler-analyzable loader - #2028
fix(CodeHighlighter): load Prism grammars through a bundler-analyzable loader#2028Div627 wants to merge 1 commit into
Conversation
…e loader
`PrismLight` is backed by `refractor/core`, which only ships
plain/plaintext/text/txt. Grammars must be registered explicitly, and the
current on-demand loader cannot do that in any bundled app:
await import(`react-syntax-highlighter/dist/esm/languages/prism/${lang}`)
A template literal over a bare specifier is not statically analyzable, so
Vite/Rollup emit it verbatim and no language chunk is ever produced. At runtime
the browser cannot resolve a bare specifier, the import throws, and the
`registerLanguage` call right after it never runs. `refractor.highlight()` then
throws `Unknown language`, react-syntax-highlighter swallows it and falls back to
a single text node — every code block renders unhighlighted, silently.
Use `PrismAsyncLight` instead: it ships a static loader map, so bundlers can
split every grammar into a real chunk, and it loads *and registers* the grammar
before re-rendering. Unsupported languages normalize to `text` rather than
warning, so the two tests asserting the old warning are updated.
`folder/FilePreview` had the same defect (raw `PrismLight`, no registration at
all) and is switched over too.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review. 📝 WalkthroughWalkthrough代码高亮组件改用 Changes异步语法高亮
Estimated code review effort: 2 (简单) | ~10 minutes Merge Risk: ⚪ Minimal · up to The PR replaces the bundler-incompatible grammar loading path with an async loader for code highlighting and file previews, with targeted tests passing. No actionable merge-blocking risk remains. Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Bundle ReportChanges will decrease total bundle size by 41 bytes (-0.0%) ⬇️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: antdx-array-pushAssets Changed:
|
nrps9909
left a comment
There was a problem hiding this comment.
The statically analyzable loader is the right direction, but exact head 4cbfc41f2ae031549df8b92b98e34ca54afa93d4 still leaves the primary Folder path unhighlighted for common file extensions.
PrismAsyncLight checks the requested string against its loader-map keys before loading. In the installed react-syntax-highlighter@16.1.1, supportedLanguages contains canonical keys such as markup, javascript, typescript, bash, python, and markdown, but not their common aliases html, js, ts, sh, py, or md. I verified this directly from PrismAsyncLight.supportedLanguages.
FilePreview.tsx passes the raw lowercased file extension as language, so .html, .js, .ts, .sh, .py, and .md files all normalize to text and remain unhighlighted. The public CodeHighlighter demo itself also passes lang="html", which now follows that fallback. This means the PR fixes the bundler failure but does not deliver syntax highlighting for many of the main consumer inputs it claims to fix.
Please add a shared alias-to-canonical normalization before both highlighters (at minimum html -> markup, js -> javascript, ts -> typescript, sh -> bash, py -> python, and md -> markdown, plus any aliases already documented/supported by the component contract). Add regression assertions that wait for actual Prism token markup for representative CodeHighlighter and Folder extension cases; checking only that <pre> exists cannot distinguish highlighting from the silent text fallback.
🤔 This is a ...
🔗 Related issue link
None — found while debugging why every code block in a Vite-bundled app renders unhighlighted.
💡 Background and solution
The bug
CodeHighlighterusesPrismLight, which is backed byrefractor/core. That instance ships onlyplain,plaintext,textandtxt:Grammars therefore have to be registered explicitly. The on-demand loader tries to do that, but it cannot work in any bundled app:
A template literal over a bare specifier is not statically analyzable. Vite/Rollup leave it in the output verbatim and emit no language chunk. Here is the expression as it appears in a production build of an app on
@ant-design/x@2.8.0:Note the empty preload dependency list. At runtime the browser cannot resolve a bare specifier, so the import throws, the
registerLanguagecall on the next line never runs, and onlyconsole.warn('[CodeHighlighter] Failed to load language: …')is left behind.refractor.highlight()then throwsUnknown language;react-syntax-highlighterswallows that ingetCodeTreeand falls back to a single text node. Every code block renders as unstyled plain text, silently.This is not fixed by upgrading.
2.8.0had noregisterLanguagecall at all;2.9.0added one, but it sits right after the import that always fails, so it never executes.folder/FilePreview.tsxhas the same defect in a more direct form — it renders rawPrismLightand never registers anything, so file previews are never highlighted either.The fix
Use
PrismAsyncLightinstead of hand-rolling the loader. It already does exactly what is needed, and does it correctly:languageLoadersmap is a static object of literalimport('refractor/<lang>')calls, so bundlers can code-split every grammar into a real chunk;textrather than throwing.folder/FilePreview.tsxis switched over too.Two tests asserted the old
console.warnbehaviour for an unsupported language.PrismAsyncLightnormalizes instead of warning, so those assertions are updated to check the graceful fallback (which is what they were really about). The now-deadjest.mockentries for the per-language modules are removed.Verification
📝 Changelog
CodeHighlighterandFolderfile preview rendering code without syntax highlighting: Prism grammars were loaded through a dynamic import that bundlers cannot analyze, so no grammar was ever registered.CodeHighlighter与Folder文件预览代码无语法高亮的问题:Prism 语法通过打包器无法分析的动态 import 加载,导致语法从未被注册。☑️ Self-Check before Merge
Summary by CodeRabbit