webui: replace hardcoded Monaco language map with dynamic detection
Replace the static language mapping in the Monaco diff editor with
Monaco's built-in language registry for automatic language detection.
Changes:
1. Remove hardcoded langMap that only supported 8 languages (js, ts, py,
html, css, json, md, go)
2. Implement dynamic language detection using monaco.languages.getLanguages()
3. Cache language list for performance since it doesn't change at runtime
4. Maintain exact extension matching including the dot prefix (.js, .ts, etc.)
5. Preserve fallback to 'plaintext' for unknown extensions
Benefits:
- Automatically supports all languages Monaco knows about (40+ languages)
- No maintenance burden when Monaco adds new language support
- Removes duplication between Monaco's registry and our hardcoded map
- Better future-proofing as Monaco language support evolves
The implementation uses Monaco's ILanguageExtensionPoint interface which
provides language.extensions arrays for each registered language. This
is more reliable than maintaining our own mapping and ensures consistency
with Monaco's actual language support.
Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: sca31f0ae899ae54dk
diff --git a/webui/src/web-components/sketch-monaco-view.ts b/webui/src/web-components/sketch-monaco-view.ts
index a1b948f..1d7363b 100644
--- a/webui/src/web-components/sketch-monaco-view.ts
+++ b/webui/src/web-components/sketch-monaco-view.ts
@@ -532,19 +532,28 @@
}
}
+ private _extensionToLanguageMap: Map<string, string> | null = null;
+
private getLanguageForFile(filename: string): string {
- const extension = filename.split(".").pop()?.toLowerCase() || "";
- const langMap: Record<string, string> = {
- js: "javascript",
- ts: "typescript",
- py: "python",
- html: "html",
- css: "css",
- json: "json",
- md: "markdown",
- go: "go",
- };
- return langMap[extension] || "plaintext";
+ // Get the file extension (including the dot for exact matching)
+ const extension = "." + (filename.split(".").pop()?.toLowerCase() || "");
+
+ // Build the extension-to-language map on first use
+ if (!this._extensionToLanguageMap) {
+ this._extensionToLanguageMap = new Map();
+ const languages = monaco.languages.getLanguages();
+
+ for (const language of languages) {
+ if (language.extensions) {
+ for (const ext of language.extensions) {
+ // Monaco extensions already include the dot, so use them directly
+ this._extensionToLanguageMap.set(ext.toLowerCase(), language.id);
+ }
+ }
+ }
+ }
+
+ return this._extensionToLanguageMap.get(extension) || "plaintext";
}
/**