Skip to content

Commit 6bfb9e6

Browse files
authored
Fix Monaco editor syntax highlighting in Preview block (#2459)
The Preview block's CodeEditPreview component was not passing file information to Monaco editor, preventing automatic language detection from file extensions. Changes: - Add fileName prop to CodeEditor component - Pass actual file path to Monaco with fallback to random UUID Fixes syntax highlighting for all text files opened in Preview blocks while maintaining backward compatibility with existing CodeEditor usage. --------- Co-authored-by: sawka
1 parent ae42e2c commit 6bfb9e6

File tree

4 files changed

+66
-6
lines changed

4 files changed

+66
-6
lines changed

frontend/app/onboarding/onboarding-command.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2025, Command Line Inc.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import { useCallback, useLayoutEffect, useState } from "react";
4+
import { useCallback, useLayoutEffect, useRef, useState } from "react";
55
import { FakeBlock } from "./onboarding-layout";
66
import waveLogo from "/logos/wave-logo.png";
77

@@ -114,6 +114,7 @@ export const ViewLogoCommand = ({ onComplete }: { onComplete?: () => void }) =>
114114
};
115115

116116
export const EditBashrcCommand = ({ onComplete }: { onComplete?: () => void }) => {
117+
const fileNameRef = useRef(`${crypto.randomUUID()}/.bashrc`);
117118
const bashrcContent = `# Aliases
118119
alias ll="ls -lah"
119120
alias gst="git status"
@@ -127,7 +128,13 @@ export PATH="$HOME/.local/bin:$PATH"`;
127128

128129
return (
129130
<FakeCommand command="wsh edit ~/.bashrc" onComplete={onComplete}>
130-
<FakeBlock icon="file-lines" name=".bashrc" editorText={bashrcContent} />
131+
<FakeBlock
132+
icon="file-lines"
133+
name=".bashrc"
134+
editorText={bashrcContent}
135+
editorFileName={fileNameRef.current}
136+
editorLanguage="shell"
137+
/>
131138
</FakeCommand>
132139
);
133140
};

frontend/app/onboarding/onboarding-layout.tsx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,21 @@ export type FakeBlockProps = {
1515
markdown?: string;
1616
imgsrc?: string;
1717
editorText?: string;
18+
editorFileName?: string;
19+
editorLanguage?: string;
1820
};
1921

20-
export const FakeBlock = ({ icon, name, highlighted, className, markdown, imgsrc, editorText }: FakeBlockProps) => {
22+
export const FakeBlock = ({
23+
icon,
24+
name,
25+
highlighted,
26+
className,
27+
markdown,
28+
imgsrc,
29+
editorText,
30+
editorFileName,
31+
editorLanguage,
32+
}: FakeBlockProps) => {
2133
return (
2234
<div
2335
className={cn(
@@ -37,7 +49,13 @@ export const FakeBlock = ({ icon, name, highlighted, className, markdown, imgsrc
3749
<div className="flex-1 flex items-center justify-center overflow-auto p-4">
3850
{editorText ? (
3951
<div className="w-full h-full">
40-
<CodeEditor blockId="fake-block" text={editorText} readonly={true} language="shell" />
52+
<CodeEditor
53+
blockId="fake-block"
54+
text={editorText}
55+
readonly={true}
56+
fileName={editorFileName}
57+
language={editorLanguage ?? "shell"}
58+
/>
4159
</div>
4260
) : imgsrc ? (
4361
<img src={imgsrc} alt={name} className="max-w-full max-h-full object-contain" />

frontend/app/view/codeeditor/codeeditor.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,19 +108,27 @@ interface CodeEditorProps {
108108
text: string;
109109
readonly: boolean;
110110
language?: string;
111+
fileName?: string;
111112
onChange?: (text: string) => void;
112113
onMount?: (monacoPtr: MonacoTypes.editor.IStandaloneCodeEditor, monaco: Monaco) => () => void;
113114
}
114115

115-
export function CodeEditor({ blockId, text, language, readonly, onChange, onMount }: CodeEditorProps) {
116+
export function CodeEditor({ blockId, text, language, fileName, readonly, onChange, onMount }: CodeEditorProps) {
116117
const divRef = useRef<HTMLDivElement>(null);
117118
const unmountRef = useRef<() => void>(null);
118119
const minimapEnabled = useOverrideConfigAtom(blockId, "editor:minimapenabled") ?? false;
119120
const stickyScrollEnabled = useOverrideConfigAtom(blockId, "editor:stickyscrollenabled") ?? false;
120121
const wordWrap = useOverrideConfigAtom(blockId, "editor:wordwrap") ?? false;
121122
const fontSize = boundNumber(useOverrideConfigAtom(blockId, "editor:fontsize"), 6, 64);
122123
const theme = "wave-theme-dark";
123-
const editorPath = useRef(crypto.randomUUID()).current;
124+
const uuidRef = useRef(crypto.randomUUID()).current;
125+
let editorPath: string;
126+
if (fileName) {
127+
const separator = fileName.startsWith("/") ? "" : "/";
128+
editorPath = blockId + separator + fileName;
129+
} else {
130+
editorPath = uuidRef;
131+
}
124132

125133
React.useEffect(() => {
126134
return () => {

frontend/app/view/preview/preview-edit.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,35 @@ import type * as MonacoTypes from "monaco-editor/esm/vs/editor/editor.api";
1212
import { useEffect } from "react";
1313
import type { SpecializedViewProps } from "./preview";
1414

15+
export const shellFileMap: Record<string, string> = {
16+
".bashrc": "shell",
17+
".bash_profile": "shell",
18+
".bash_login": "shell",
19+
".bash_logout": "shell",
20+
".profile": "shell",
21+
".zshrc": "shell",
22+
".zprofile": "shell",
23+
".zlogin": "shell",
24+
".zlogout": "shell",
25+
".kshrc": "shell",
26+
".cshrc": "shell",
27+
".tcshrc": "shell",
28+
".xonshrc": "python",
29+
".shrc": "shell",
30+
".aliases": "shell",
31+
".functions": "shell",
32+
".exports": "shell",
33+
".direnvrc": "shell",
34+
};
35+
1536
function CodeEditPreview({ model }: SpecializedViewProps) {
1637
const fileContent = useAtomValue(model.fileContent);
1738
const setNewFileContent = useSetAtom(model.newFileContent);
1839
const fileInfo = useAtomValue(model.statFile);
40+
const fileName = fileInfo?.path || fileInfo?.name;
41+
42+
const baseName = fileName ? fileName.split("/").pop() : null;
43+
const language = baseName && shellFileMap[baseName] ? shellFileMap[baseName] : undefined;
1944

2045
function codeEditKeyDownHandler(e: WaveKeyboardEvent): boolean {
2146
if (checkKeyPressed(e, "Cmd:e")) {
@@ -65,6 +90,8 @@ function CodeEditPreview({ model }: SpecializedViewProps) {
6590
<CodeEditor
6691
blockId={model.blockId}
6792
text={fileContent}
93+
fileName={fileName}
94+
language={language}
6895
readonly={fileInfo.readonly}
6996
onChange={(text) => setNewFileContent(text)}
7097
onMount={onMount}

0 commit comments

Comments
 (0)