feat: add C# syntax highlighting#1651
Conversation
|
| Filename | Overview |
|---|---|
| packages/highlight/src/parsers.ts | Adds cs: csharpLanguage.parser entry following the identical pattern used by Java, Rust, and Swift; import and registration are clean. |
| packages/app/src/components/highlighted-code-block.tsx | Adds csharp and c# aliases to the LANGUAGE_ALIASES map; consistent with the existing alias table and the fenceLanguageToExtension logic. |
| packages/highlight/package.json | Adds @replit/codemirror-lang-csharp: ^6.2.0 to dependencies; all peers are satisfied by existing CodeMirror 6 packages in the project. |
| packages/highlight/src/tests/highlighter.test.ts | New C# test case mirrors the Dart/Swift/Python pattern — asserts class → keyword and string literal → string style. |
| packages/highlight/src/tests/parsers.test.ts | Adds test.cs to isLanguageSupported and cs to getSupportedExtensions checks; follows the existing test structure. |
| package-lock.json | Adds only the @replit/codemirror-lang-csharp node and the one reference in packages/highlight; previously-flagged lockfile churn was addressed in the fixup commit. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["Markdown fence / file path\ne.g. ```csharp or file.cs"] --> B["fenceLanguageToExtension\nor getParserForFile"]
B --> C{"LANGUAGE_ALIASES lookup\n(highlighted-code-block.tsx)"}
C -- "csharp / c# → cs" --> D["extension = 'cs'"]
C -- "already an ext key\n(e.g. 'cs')" --> D
D --> E["parsersByExtension\n(parsers.ts)"]
E --> F["csharpLanguage.parser\n(@replit/codemirror-lang-csharp)"]
F --> G["highlightCode → token stream\nwith keyword / string / type styles"]
%%{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"}}}%%
flowchart TD
A["Markdown fence / file path\ne.g. ```csharp or file.cs"] --> B["fenceLanguageToExtension\nor getParserForFile"]
B --> C{"LANGUAGE_ALIASES lookup\n(highlighted-code-block.tsx)"}
C -- "csharp / c# → cs" --> D["extension = 'cs'"]
C -- "already an ext key\n(e.g. 'cs')" --> D
D --> E["parsersByExtension\n(parsers.ts)"]
E --> F["csharpLanguage.parser\n(@replit/codemirror-lang-csharp)"]
F --> G["highlightCode → token stream\nwith keyword / string / type styles"]
Reviews (3): Last reviewed commit: "feat: add C# syntax highlighting" | Re-trigger Greptile
Wire the @replit/codemirror-lang-csharp Lezer grammar into @getpaseo/highlight following the existing per-language pattern (Java/Rust/Swift). Map the cs extension to the parser and alias the csharp and c# markdown fence names so fenced code blocks highlight. Register csharpLanguage.parser rather than the package's raw parser export: the highlight styleTags are applied only inside csharpLanguage (via parser.configure), so the raw parser would parse but render unstyled. Closes getpaseo#1527 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ed119dc to
4294ed5
Compare
Linked issue
Closes #1527
Type of change
What does this PR do
Adds C# (
.cs) syntax highlighting, implementing the request in #1527 (proposed with a patch by @percyboy). It wires the@replit/codemirror-lang-csharpLezer grammar into@getpaseo/highlightfollowing the existing per-language pattern (Java/Rust/Swift), and aliases thecsharp/c#markdown fence names tocs.This makes C# highlight everywhere code is rendered through the shared highlighter — the file viewer, diff views, and
```csharp/```cs/```c#markdown code fences in agent messages.One deliberate change from the patch in the issue: I register
csharpLanguage.parser, not the package's rawparserexport. The Replit package applies its highlightstyleTagsonly insidecsharpLanguage(viaparser.configure), so the raw parser would produce a valid tree but render with no highlighting. This differs from@lezer/javaetc., whoseparserexport ships highlight props baked in.Changed files:
packages/highlight/package.json— add@replit/codemirror-lang-csharppackages/highlight/src/parsers.ts— registercs: csharpLanguage.parserpackages/app/src/components/highlighted-code-block.tsx—csharp/c#fence aliasespackages/highlight/src/__tests__/*— parser + highlighter test casesHow did you verify it
Added unit tests and ran the two changed suites:
npx vitest run packages/highlight/src/__tests__/{parsers,highlighter}.test.ts→ 23 passed, including the new C# cases (assertsclass→ keyword, string → string).npm run build:serverthennpm run typecheck→ clean across all workspaces.npm run lint→ 0 warnings / 0 errors.npm run format→ clean.Opened a real
.csfile (Program.cs) in the running Paseo app and confirmed full highlighting (keywords, types, method names,switchpattern matching, interpolated strings, LINQ, comments), on web and desktop (Electron):Web (browser):
Desktop (Electron):

Verified on web + desktop; iOS/Android render through the identical cross-platform component (no platform-gated code in the highlight path), so they were not separately captured.
Checklist
npm run typecheckpassesnpm run lintpassesnpm run formatran (Biome)