Skip to content

fix(editor): map Salesforce Apex extensions to the apex language id - #14287

Merged
AmethystLiang merged 3 commits into
stablyai:mainfrom
bdJohnson72:fix/apex-syntax-highlighting
Sep 23, 2026
Merged

AmethystLiang merged 3 commits into
stablyai:mainfrom
bdJohnson72:fix/apex-syntax-highlighting

Conversation

@bdJohnson72

@bdJohnson72 bdJohnson72 commented Aug 13, 2026 •

Copy link
Copy Markdown
Contributor

ELI5

Salesforce Apex files (.cls classes, .trigger triggers, .apex scripts) opened in Orca's editor as plain black-and-white text. Orca already ships the Apex coloring rules. It just never told the editor to use them for these file types. Now it does.

What Changed

  • Before: opening AccountService.cls or AccountTrigger.trigger showed monochrome text. Line numbers, bracket matching, and folding worked, but there was no highlighting. .xml/.js/.md files in the same repo highlighted normally.
  • After: these files open with Apex highlighting (keywords, types, strings, comments, inline SOQL). That applies to file tabs and to every other view that asks Orca for a file's language, such as diffs, conflict review, and review-comment code snippets.
  • Mechanism: Orca chooses the editor language itself, in detectLanguage (src/renderer/src/lib/language-detect.ts), and passes it to Monaco explicitly. An explicit language overrides Monaco's own extension lookup, so Monaco's built-in .cls → apex registration never ran, and unknown extensions fell back to plaintext. This PR adds .cls, .trigger, and .apex to Orca's map, pointing at Monaco's bundled apex grammar. Monaco doesn't register .trigger or .apex at all, so they needed an entry either way.

Why

The other option was to let Monaco guess from the file extension whenever Orca's map has no entry. That would cover more file types at once. But Orca's editor model URIs are synthetic, and each editor view (file tab, diff, conflict review, excerpts) creates its own models, so that change would touch several views and belongs in its own PR. Adding a map entry matches how .liquid, .proto, and .jsp were added, and keeps detectLanguage a pure lookup that doesn't depend on Monaco. No new grammar or dependency is added. Monaco loads the Apex grammar only when an Apex file is opened.

Linked Issue

Fixes #22049

Supersedes #22121, which made the same fix independently later. Its author is credited as a co-author.

Visual Proof

Before (reported here):

before: .cls renders as plaintext

After, dev build of this branch, files opened from the file explorer (both tabs report language apex):

apex-after-cls.png
apex-after-trigger.png

Testing

  • I manually tested these changes locally (macOS dev build: opened a .cls and a .trigger from the file explorer; both highlight as Apex)

  • Automated tests added/updated

  • vitest run src/renderer/src/lib/language-detect.test.ts: 16 passed. The new case covers .cls, .trigger, .apex, and an uppercase Windows path. It fails without the map change (expected 'plaintext' to be 'apex').

  • pnpm tc:web, oxlint, oxfmt --check, pnpm run check:code-quality:changed: pass.

AI Disclosure

Maintainer follow-up commits were made with Claude (Opus 5.5).

Review

The original commit is by @bdJohnson72. Maintainer changes on top of it:

  • merged current main. The test file conflicted with the .liquid test added since; both tests are kept.
  • shortened the code comment to one line.

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

  • Cross-platform: the extension lookup ignores case and handles both / and \ paths (tested).
  • SSH / remote: only the file path is inspected, in the renderer. No host or wire change.
  • Mobile: unchanged. Mobile has its own map and highlights with lowlight's common grammars, which don't include Apex, so an apex id falls back to plaintext there as before.
  • Performance: one extra map entry per extension. The grammar loads lazily.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

Monaco's built-in registry already declares the 'apex' language and ships
its tokenizer, registered for '.cls'. But detectLanguage resolves the
language id before Monaco's own extension lookup runs, and the editor is
mounted with that id as an explicit prop, so Monaco's inference never
fires. Apex sources fell through to 'plaintext'.

Map '.cls', '.trigger' and '.apex' onto the existing 'apex' grammar.
No new grammar is added -- this only reaches the one already bundled.
@coderabbitai

coderabbitai Bot commented Aug 13, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: a9890e30-f09e-4a1d-8c7b-82b3c51e930c

📥 Commits

Reviewing files that changed from the base of the PR and between 54812c7 and d7bb5cc.

📒 Files selected for processing (2)
  • src/renderer/src/lib/language-detect.test.ts
  • src/renderer/src/lib/language-detect.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 6 remain after this review.


📝 Walkthrough

Walkthrough

The language detector maps .cls, .trigger, and .apex files to the apex language identifier. Tests cover these extensions and a mixed-case Windows path.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to d7bb5

The renderer now recognizes the listed Apex file types for syntax highlighting. No actionable merge risk is established by the supplied review context.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
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.
Title check ✅ Passed The title clearly and concisely describes the main change: mapping Salesforce Apex file extensions to Monaco’s Apex language ID.
Description check ✅ Passed The description covers the required sections with a clear explanation of the change, rationale, linked issue, visual proof, testing, AI disclosure, and checklist. The Review section is empty, but this…

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.

@DannyGelf

Copy link
Copy Markdown

BEFORE screenshot:
image

I opened an issue before I found this PR - stablyai/orca#22049

AmethystLiang and others added 2 commits September 22, 2026 15:26
# Conflicts:
#	src/renderer/src/lib/language-detect.test.ts
Also credit the duplicate fix in stablyai#22121, which reached the same change independently.

Co-authored-by: Nurdaulet Bolat <204565446+nvimq@users.noreply.github.com>
@AmethystLiang
AmethystLiang merged commit 942d993 into stablyai:main Sep 23, 2026
29 checks passed
ggbdpq added a commit to ggbdpq/orca that referenced this pull request Sep 30, 2026
`.rake`, `.ru`, `.jbuilder` and `.thor` sources opened as plaintext: the
generated `monaco-language-associations.json` only carries Monaco's ruby
registration (`.rb/.rbx/.rjs/.gemspec/.pp` plus `rakefile`/`Gemfile`), and
that file is rewritten from Monaco by `generate-monaco-associations.mjs`,
so curated entries belong in the hand-maintained `language-detect.ts` maps
(same shape as the merged Apex precedent stablyai#14287).

Add the four extensions plus the Guardfile/Capfile/Podfile/Brewfile/
Vagrantfile DSL filenames, with case-insensitive extension coverage and
near-miss negatives (`report.rake.bak`, `ruby.rakex` stay plaintext).

Fixes stablyai#24145

Generated-by: GLM-5.3-Flash (ZCode)
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.

[Bug]: Apex .cls files render as plaintext despite the bundled Monaco Apex grammar

5 participants