Skip to content

UN-3185 [FIX] Restore global Prism for prismjs add-ons (Prompt Studio detail + HITL blank page)#2135

Merged
kirtimanmishrazipstack merged 4 commits into
mainfrom
fix/un3185-prism-global
Jul 1, 2026
Merged

UN-3185 [FIX] Restore global Prism for prismjs add-ons (Prompt Studio detail + HITL blank page)#2135
kirtimanmishrazipstack merged 4 commits into
mainfrom
fix/un3185-prism-global

Conversation

@ritwik-g

@ritwik-g ritwik-g commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Problem

On the latest Vite build, the Prompt Studio detail page and the HITL / manual-review page render blank (ErrorBoundary fallback). Console shows:

ReferenceError: Prism is not defined

Both pages share the Combined Output viewer (CombinedOutput.jsx), which is where the crash originates.

Root cause

CombinedOutput.jsx loads PrismJS language/plugin add-ons:

import "prismjs";                        // meant to install the global Prism
import "prismjs/components/prism-json";  // does `Prism.languages.json = …` on a BARE global
import "prismjs/plugins/line-numbers/prism-line-numbers.js"; // same bare-global reliance

prismjs/components/prism-json.js has no imports — it references a free global Prism and relies on import "prismjs" having installed it first.

import "prismjs" is a side-effect-only import with no used bindings, so the Vite/Rollup production build tree-shakes it away. Nothing installs the global, and the add-ons throw ReferenceError: Prism is not defined at module evaluation, taking down the whole Combined Output subtree.

Confirmed by inspecting the production bundle before this fix: the chunk runs Prism.languages.json = {…} with no window.Prism/globalThis.Prism assignment anywhere in the output. The prism imports are unchanged since the initial commit — only the bundler (CRA/webpack → Vite) changed, which is why this only surfaces on the new build.

Fix

  • New frontend/src/helpers/prismSetup.js — imports Prism core with a used binding (tree-shake-proof) and pins it on globalThis.
  • CombinedOutput.jsx — import prismSetup before the add-ons so the global is guaranteed present when they evaluate. ESM evaluates a sibling dependency fully (body included) before the next, so ordering is guaranteed.

Verification

Production vite build of the fixed tree — the emitted chunk now runs:

 !globalThis.Prism && (globalThis.Prism = <core>); Prism.languages.json = {}

i.e. the global is installed immediately before the add-on uses it. Build succeeds; no new warnings.

Note: not yet exercised against a live running on-prem instance (needs backend/login) — a standalone fixed build/image was produced for that manual test.

🤖 Generated with Claude Code

… detail + HITL blank page)

The Vite production build tree-shakes the bare `import "prismjs"` in
CombinedOutput.jsx (a side-effect-only import with no used bindings), so
nothing installs the global `Prism` that `prismjs/components/prism-json`
and the line-numbers plugin reference. Those add-ons then throw
`ReferenceError: Prism is not defined` at module evaluation, crashing the
Combined Output viewer shared by the Prompt Studio detail page and the
HITL / manual-review page (both render blank). The old CRA/webpack build
did not tree-shake it, so the regression only surfaces on the Vite build.

Add a dedicated prismSetup module that imports Prism core with a *used*
binding (survives tree-shaking) and pins it on globalThis, and import it
before the add-ons in CombinedOutput so the global is guaranteed present
by the time the add-on modules evaluate.

Verified against a production `vite build`: the emitted chunk now runs
`globalThis.Prism = <core>` immediately before `Prism.languages.json = ...`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 15be849c-a5fd-4558-a397-a6320eaa660d

📥 Commits

Reviewing files that changed from the base of the PR and between 5ad4e78 and e0db7f3.

📒 Files selected for processing (3)
  • frontend/src/components/custom-tools/combined-output/CombinedOutput.jsx
  • frontend/src/helpers/prismSetup.js
  • frontend/src/index.jsx
✅ Files skipped from review due to trivial changes (1)
  • frontend/src/index.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/helpers/prismSetup.js

Summary by CodeRabbit

  • Bug Fixes
    • Improved syntax highlighting reliability in the combined output view.
    • Ensured Prism is initialized safely at app startup before syntax add-ons load, preventing missing or broken highlighting in some browser builds.

Walkthrough

Prism is now initialized through a bootstrap helper that assigns the imported core to globalThis.Prism, and the app entry loads that helper before lazy chunks. The combined output component no longer imports Prism core directly.

Changes

Prism Global Setup

Layer / File(s) Summary
Bootstrap setup and consumer import
frontend/src/index.jsx, frontend/src/helpers/prismSetup.js, frontend/src/components/custom-tools/combined-output/CombinedOutput.jsx
The entry point imports the Prism setup helper early, the helper imports Prism core and assigns it to globalThis.Prism, and the combined output component removes its direct prismjs import while keeping its Prism add-on/theme imports.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is detailed but does not follow the required template and omits several mandatory sections, including explicit breakage, migrations, env config, and checklist. Reformat it to the repository template and add explicit answers for breakage, database migrations, env config, related issues, testing, screenshots, and checklist.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the Prism global fix and the affected blank-page issue.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/un3185-prism-global

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a production crash (ReferenceError: Prism is not defined) that blanked the Prompt Studio detail page and HITL review page after the CRA → Vite migration. The root cause was that import "prismjs" in CombinedOutput.jsx was a side-effect-only binding that Vite's production build tree-shook away, leaving the prism-json and prism-line-numbers add-ons with no global to register onto.

  • A new helpers/prismSetup.js module imports Prism with a named binding (preventing tree-shaking) and assigns it unconditionally to globalThis.Prism, ensuring the exact same instance the add-ons extend is the one Prism.highlightAll() reads.
  • index.jsx imports prismSetup.js as its very first static import so the global is guaranteed to be installed before any lazy-loaded chunk — including the shared chunk holding the add-ons — can evaluate.

Confidence Score: 5/5

Safe to merge — the change is a targeted bootstrap fix with no logic changes to any component or data flow.

Three small, focused changes: a new 20-line helper that pins Prism to globalThis, removal of one side-effect import from CombinedOutput.jsx, and a single import line added to the entry point. The fix is verified in production by inspecting the emitted Vite bundle, all other prismjs consumers in the codebase use named bindings and are unaffected, and no existing behavior outside the crash path is altered.

No files require special attention.

Important Files Changed

Filename Overview
frontend/src/helpers/prismSetup.js New bootstrap module: imports Prism with a named binding (tree-shake-proof) and unconditionally pins it to globalThis so add-ons that reference a bare global Prism can safely evaluate in any lazy chunk.
frontend/src/components/custom-tools/combined-output/CombinedOutput.jsx Removes the tree-shakeable import "prismjs" side-effect import; retains the add-on imports which are now safe because prismSetup.js is guaranteed to have run first via the entry-point import.
frontend/src/index.jsx Adds import "./helpers/prismSetup" as the first static import so the global Prism assignment executes at bootstrap, before any lazy route chunk can load.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Entry as index.jsx (entry chunk)
    participant Setup as helpers/prismSetup.js
    participant PrismCore as prismjs core
    participant Global as globalThis
    participant LazyChunk as lazy chunk (CombinedOutput)
    participant Addons as prism-json / prism-line-numbers

    Entry->>Setup: import "./helpers/prismSetup" (static, first)
    Setup->>PrismCore: import Prism from "prismjs" (named binding)
    PrismCore-->>Setup: Prism singleton
    Setup->>Global: "globalThis.Prism = Prism"
    Note over Global: Prism is now installed

    Note over Entry: Entry chunk fully evaluated

    Note over LazyChunk: User navigates → dynamic import fires
    Entry->>LazyChunk: import() CombinedOutput
    LazyChunk->>Addons: import "prismjs/components/prism-json"
    Addons->>Global: reads globalThis.Prism ✓
    Addons->>Global: "Prism.languages.json = {…}"
    LazyChunk->>Addons: import "prismjs/plugins/line-numbers/prism-line-numbers.js"
    Addons->>Global: reads globalThis.Prism ✓
    Note over LazyChunk: Component renders correctly
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Entry as index.jsx (entry chunk)
    participant Setup as helpers/prismSetup.js
    participant PrismCore as prismjs core
    participant Global as globalThis
    participant LazyChunk as lazy chunk (CombinedOutput)
    participant Addons as prism-json / prism-line-numbers

    Entry->>Setup: import "./helpers/prismSetup" (static, first)
    Setup->>PrismCore: import Prism from "prismjs" (named binding)
    PrismCore-->>Setup: Prism singleton
    Setup->>Global: "globalThis.Prism = Prism"
    Note over Global: Prism is now installed

    Note over Entry: Entry chunk fully evaluated

    Note over LazyChunk: User navigates → dynamic import fires
    Entry->>LazyChunk: import() CombinedOutput
    LazyChunk->>Addons: import "prismjs/components/prism-json"
    Addons->>Global: reads globalThis.Prism ✓
    Addons->>Global: "Prism.languages.json = {…}"
    LazyChunk->>Addons: import "prismjs/plugins/line-numbers/prism-line-numbers.js"
    Addons->>Global: reads globalThis.Prism ✓
    Note over LazyChunk: Component renders correctly
Loading

Reviews (4): Last reviewed commit: "UN-3185 [FIX] Install global Prism eager..." | Re-trigger Greptile

Comment thread frontend/src/helpers/prismSetup.js Outdated
ritwik-g and others added 3 commits July 1, 2026 12:07
Drop the always-true `typeof globalThis !== "undefined"` check — globalThis
is universally available in any ESM/Vite target. Addresses Greptile review.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…e (review)

Address PR review:
- silent-failure-hunter: a `!globalThis.Prism` guard could leave a different,
  pre-existing Prism in place, so the add-ons extend one instance while
  JsonView's highlightAll() reads another -> JSON silently unhighlighted.
  Assign unconditionally so the global is provably our core instance.
- comment-analyzer: the prior comment blamed evaluation order yet relied on it
  to justify the fix. Rewrite: relying on prismjs core's self-install is
  unreliable under code-splitting; the explicit globalThis assignment (from
  first-party code imported before the add-ons) is the deterministic fix.

Rebuilt: emitted chunk runs `globalThis.Prism = <core>` immediately before
`Prism.languages.json = ...`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Verified against the actual on-prem image (built with the manual-review
plugin): the per-component prismSetup import did NOT fix it. Because
manual-review's ResultEditor also imports `prismjs/components/prism-json`,
Rollup hoists that add-on into a SHARED lazy chunk (PdfViewer), separate
from CombinedOutput's chunk where prismSetup ran — with no ordering
guarantee between two lazy chunks, so the add-on still evaluated before the
global was installed. My local OSS build masked this: with no manual-review
plugin, prism-json wasn't shared and stayed in CombinedOutput's chunk.

Fix: import prismSetup EAGERLY from index.jsx so `globalThis.Prism` is
installed at bootstrap, before any lazy chunk (including the shared add-on
chunk) can load. Robust regardless of how Rollup hoists prism-json.

Reproduced the shared-chunk hoist locally (two independent lazy prism-json
importers) and confirmed: prism-json lands in its own lazy chunk while
globalThis.Prism stays in the eager entry <script type=module>, so the
global is always installed first. Fixes both the Prompt Studio detail page
and the HITL review page.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Frontend Lint Report (Biome)

All checks passed! No linting or formatting issues found.

@ritwik-g

ritwik-g commented Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

Update: moved the Prism global-install to the app entry (fixes HITL too)

Testing the built on-prem image revealed the per-component prismSetup import was not sufficient. Root cause refinement:

  • The manual-review plugin's ResultEditor (the HITL viewer, present in on-prem/enterprise builds) also imports prismjs/components/prism-json. With two independent lazy importers, Rollup hoists prism-json into a shared lazy chunk (PdfViewer), separate from the CombinedOutput chunk where prismSetup ran. There's no evaluation-order guarantee between two lazy chunks, so the add-on still ran before the global was installed → ReferenceError persisted on both pages.
  • My earlier local OSS build masked this: without the manual-review plugin, prism-json wasn't shared and stayed in CombinedOutput's chunk.

Fix (e0db7f3): import prismSetup eagerly from index.jsx, so globalThis.Prism is installed at bootstrap — before any lazy chunk (including the shared add-on chunk) can load. Robust regardless of how Rollup hoists the add-ons.

Verified in the built bundle: globalThis.Prism = <core> lands in the eager entry <script type=module>, while prism-json stays in a lazy chunk. I also reproduced the shared-chunk hoist locally (two independent lazy prism-json importers) and confirmed the global is still installed first. Rebuilding the on-prem image for a live test.

@sonarqubecloud

sonarqubecloud Bot commented Jul 1, 2026

Copy link
Copy Markdown

@kirtimanmishrazipstack kirtimanmishrazipstack merged commit 71c55e5 into main Jul 1, 2026
9 checks passed
@kirtimanmishrazipstack kirtimanmishrazipstack deleted the fix/un3185-prism-global branch July 1, 2026 07:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants