Files
paseo/packages/app/src/file-pane/editor/extensions.web.ts
T
Mohamed BoudraandGitHub 4bda2dfea9 Edit workspace files directly on web (#2270)
* feat(files): edit workspace files on web

Keep source buffers synchronized with host file changes and require an explicit overwrite or reload when revisions diverge.

* feat(panels): surface and protect modified tabs

Expose tooltip and modification state through the generic panel boundary so tabs can show stable metadata and guard every close route consistently.

* fix(tests): use portable fake timeout handle

* fix(files): harden editor conflict handling

Preserve modified panel state across tab eviction, use precise revisions for optimistic writes, coalesce concurrent file watchers, and localize the editor interface.

* fix(files): close editor concurrency gaps

Coalesce clean reloads, preserve subscriber identities and file permissions, suspend pending saves during close confirmation, and carry precise revisions through file reads.

* test(files): expect read revision metadata
2026-07-21 04:41:19 +08:00

88 lines
2.5 KiB
TypeScript

import { defaultKeymap, history, historyKeymap, indentWithTab } from "@codemirror/commands";
import {
bracketMatching,
defaultHighlightStyle,
indentOnInput,
syntaxHighlighting,
} from "@codemirror/language";
import { searchKeymap } from "@codemirror/search";
import {
EditorView,
drawSelection,
highlightActiveLine,
keymap,
lineNumbers,
} from "@codemirror/view";
import { createCodeMirrorHighlightStyle, type HighlightStyle } from "@getpaseo/highlight";
export interface EditorVisualTheme {
colorScheme: "light" | "dark";
background: string;
foreground: string;
cursor: string;
foregroundMuted: string;
border: string;
selection: string;
monoFont: string;
codeFontSize: number;
syntax: Record<HighlightStyle, string>;
}
export function editorBaseExtensions(onSave: () => void) {
return [
lineNumbers(),
history(),
drawSelection(),
indentOnInput(),
bracketMatching(),
highlightActiveLine(),
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
keymap.of([
{ key: "Mod-s", preventDefault: true, run: () => (onSave(), true) },
indentWithTab,
...defaultKeymap,
...historyKeymap,
...searchKeymap,
]),
];
}
export function editorTheme(theme: EditorVisualTheme) {
return [
EditorView.theme(
{
"&": {
height: "100%",
backgroundColor: theme.background,
color: theme.foreground,
fontFamily: theme.monoFont,
fontSize: `${theme.codeFontSize}px`,
},
".cm-scroller": {
overflow: "auto",
fontFamily: theme.monoFont,
lineHeight: "1.45",
},
".cm-content": { caretColor: theme.foreground, padding: "16px 0" },
".cm-cursor, .cm-dropCursor": { borderLeftColor: theme.cursor },
".cm-gutters": {
backgroundColor: theme.background,
color: theme.foregroundMuted,
borderRight: `1px solid ${theme.border}`,
},
".cm-activeLine": { backgroundColor: "transparent" },
".cm-activeLineGutter": { backgroundColor: "transparent", color: theme.foreground },
"&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
backgroundColor: theme.selection,
},
".cm-selectionBackground, ::selection": {
backgroundColor: theme.selection,
},
"&.cm-focused": { outline: "none" },
},
{ dark: theme.colorScheme === "dark" },
),
syntaxHighlighting(createCodeMirrorHighlightStyle(theme.syntax)),
];
}