195 lines
6.7 KiB
TypeScript
195 lines
6.7 KiB
TypeScript
/**
|
|
* Unified language mapping for all editor implementations.
|
|
* Maps file extensions to language IDs for Monaco, CodeMirror, and lowlight.
|
|
*/
|
|
|
|
type LanguageIds = {
|
|
monaco: string;
|
|
codemirror: string;
|
|
lowlight: string;
|
|
};
|
|
|
|
const LANGUAGE_MAP: Record<string, LanguageIds> = {
|
|
// JavaScript/TypeScript
|
|
".js": { monaco: "javascript", codemirror: "javascript", lowlight: "javascript" },
|
|
".mjs": { monaco: "javascript", codemirror: "javascript", lowlight: "javascript" },
|
|
".cjs": { monaco: "javascript", codemirror: "javascript", lowlight: "javascript" },
|
|
".jsx": { monaco: "javascript", codemirror: "jsx", lowlight: "javascript" },
|
|
".ts": { monaco: "typescript", codemirror: "typescript", lowlight: "typescript" },
|
|
".mts": { monaco: "typescript", codemirror: "typescript", lowlight: "typescript" },
|
|
".cts": { monaco: "typescript", codemirror: "typescript", lowlight: "typescript" },
|
|
".tsx": { monaco: "typescript", codemirror: "tsx", lowlight: "typescript" },
|
|
|
|
// Python
|
|
".py": { monaco: "python", codemirror: "python", lowlight: "python" },
|
|
".pyw": { monaco: "python", codemirror: "python", lowlight: "python" },
|
|
".pyi": { monaco: "python", codemirror: "python", lowlight: "python" },
|
|
|
|
// Go
|
|
".go": { monaco: "go", codemirror: "go", lowlight: "go" },
|
|
|
|
// Rust
|
|
".rs": { monaco: "rust", codemirror: "rust", lowlight: "rust" },
|
|
|
|
// Ruby
|
|
".rb": { monaco: "ruby", codemirror: "ruby", lowlight: "ruby" },
|
|
".erb": { monaco: "ruby", codemirror: "ruby", lowlight: "erb" },
|
|
|
|
// Java/JVM
|
|
".java": { monaco: "java", codemirror: "java", lowlight: "java" },
|
|
".kt": { monaco: "kotlin", codemirror: "kotlin", lowlight: "kotlin" },
|
|
".kts": { monaco: "kotlin", codemirror: "kotlin", lowlight: "kotlin" },
|
|
".scala": { monaco: "scala", codemirror: "scala", lowlight: "scala" },
|
|
".groovy": { monaco: "groovy", codemirror: "groovy", lowlight: "groovy" },
|
|
|
|
// Swift
|
|
".swift": { monaco: "swift", codemirror: "swift", lowlight: "swift" },
|
|
|
|
// C/C++
|
|
".c": { monaco: "c", codemirror: "cpp", lowlight: "c" },
|
|
".h": { monaco: "c", codemirror: "cpp", lowlight: "c" },
|
|
".cpp": { monaco: "cpp", codemirror: "cpp", lowlight: "cpp" },
|
|
".cc": { monaco: "cpp", codemirror: "cpp", lowlight: "cpp" },
|
|
".cxx": { monaco: "cpp", codemirror: "cpp", lowlight: "cpp" },
|
|
".hpp": { monaco: "cpp", codemirror: "cpp", lowlight: "cpp" },
|
|
".hxx": { monaco: "cpp", codemirror: "cpp", lowlight: "cpp" },
|
|
|
|
// C#
|
|
".cs": { monaco: "csharp", codemirror: "csharp", lowlight: "csharp" },
|
|
|
|
// PHP
|
|
".php": { monaco: "php", codemirror: "php", lowlight: "php" },
|
|
|
|
// Web
|
|
".html": { monaco: "html", codemirror: "html", lowlight: "xml" },
|
|
".htm": { monaco: "html", codemirror: "html", lowlight: "xml" },
|
|
".css": { monaco: "css", codemirror: "css", lowlight: "css" },
|
|
".scss": { monaco: "scss", codemirror: "css", lowlight: "scss" },
|
|
".sass": { monaco: "scss", codemirror: "css", lowlight: "scss" },
|
|
".less": { monaco: "less", codemirror: "css", lowlight: "less" },
|
|
|
|
// Data formats
|
|
".json": { monaco: "json", codemirror: "json", lowlight: "json" },
|
|
".jsonc": { monaco: "json", codemirror: "json", lowlight: "json" },
|
|
".yaml": { monaco: "yaml", codemirror: "yaml", lowlight: "yaml" },
|
|
".yml": { monaco: "yaml", codemirror: "yaml", lowlight: "yaml" },
|
|
".xml": { monaco: "xml", codemirror: "html", lowlight: "xml" },
|
|
".toml": { monaco: "ini", codemirror: "toml", lowlight: "ini" },
|
|
".ini": { monaco: "ini", codemirror: "ini", lowlight: "ini" },
|
|
".env": { monaco: "ini", codemirror: "properties", lowlight: "ini" },
|
|
|
|
// Markup
|
|
".md": { monaco: "markdown", codemirror: "markdown", lowlight: "markdown" },
|
|
".mdx": { monaco: "markdown", codemirror: "markdown", lowlight: "markdown" },
|
|
|
|
// Shell
|
|
".sh": { monaco: "shell", codemirror: "bash", lowlight: "bash" },
|
|
".bash": { monaco: "shell", codemirror: "bash", lowlight: "bash" },
|
|
".zsh": { monaco: "shell", codemirror: "bash", lowlight: "bash" },
|
|
".fish": { monaco: "shell", codemirror: "fish", lowlight: "bash" },
|
|
|
|
// SQL
|
|
".sql": { monaco: "sql", codemirror: "sql", lowlight: "sql" },
|
|
|
|
// Docker
|
|
".dockerfile": { monaco: "dockerfile", codemirror: "dockerfile", lowlight: "dockerfile" },
|
|
|
|
// GraphQL
|
|
".graphql": { monaco: "graphql", codemirror: "graphql", lowlight: "graphql" },
|
|
".gql": { monaco: "graphql", codemirror: "graphql", lowlight: "graphql" },
|
|
|
|
// Vue/Svelte
|
|
".vue": { monaco: "html", codemirror: "vue", lowlight: "xml" },
|
|
".svelte": { monaco: "html", codemirror: "svelte", lowlight: "xml" },
|
|
};
|
|
|
|
/**
|
|
* Language name aliases (used when a language string is provided instead of file ext).
|
|
* Maps common language names to Monaco language IDs.
|
|
*/
|
|
const LANGUAGE_ALIASES: Record<string, string> = {
|
|
javascript: "javascript",
|
|
js: "javascript",
|
|
jsx: "javascript",
|
|
typescript: "typescript",
|
|
ts: "typescript",
|
|
tsx: "typescript",
|
|
python: "python",
|
|
py: "python",
|
|
go: "go",
|
|
golang: "go",
|
|
rust: "rust",
|
|
rs: "rust",
|
|
java: "java",
|
|
kotlin: "kotlin",
|
|
scala: "scala",
|
|
swift: "swift",
|
|
c: "c",
|
|
cpp: "cpp",
|
|
"c++": "cpp",
|
|
csharp: "csharp",
|
|
"c#": "csharp",
|
|
php: "php",
|
|
ruby: "ruby",
|
|
rb: "ruby",
|
|
html: "html",
|
|
css: "css",
|
|
scss: "scss",
|
|
less: "less",
|
|
json: "json",
|
|
yaml: "yaml",
|
|
yml: "yaml",
|
|
xml: "xml",
|
|
markdown: "markdown",
|
|
md: "markdown",
|
|
bash: "shell",
|
|
shell: "shell",
|
|
sh: "shell",
|
|
zsh: "shell",
|
|
sql: "sql",
|
|
dockerfile: "dockerfile",
|
|
graphql: "graphql",
|
|
plaintext: "plaintext",
|
|
text: "plaintext",
|
|
};
|
|
|
|
function getExtension(filePath: string): string {
|
|
const lastSlash = filePath.lastIndexOf("/");
|
|
const name = lastSlash >= 0 ? filePath.slice(lastSlash + 1) : filePath;
|
|
|
|
// Handle Dockerfile (no extension)
|
|
if (name.toLowerCase() === "dockerfile") return ".dockerfile";
|
|
|
|
const dot = name.lastIndexOf(".");
|
|
if (dot === -1) return "";
|
|
return name.slice(dot).toLowerCase();
|
|
}
|
|
|
|
export function getMonacoLanguage(filePath: string): string {
|
|
const ext = getExtension(filePath);
|
|
return LANGUAGE_MAP[ext]?.monaco ?? "plaintext";
|
|
}
|
|
|
|
export function getMonacoLanguageFromName(language: string): string {
|
|
return LANGUAGE_ALIASES[language.toLowerCase()] ?? "plaintext";
|
|
}
|
|
|
|
export function getLowlightLanguage(filePath: string): string {
|
|
const ext = getExtension(filePath);
|
|
return LANGUAGE_MAP[ext]?.lowlight ?? "plaintext";
|
|
}
|
|
|
|
export function getLowlightLanguageFromName(language: string): string {
|
|
// For lowlight, the language name is typically the same
|
|
const lower = language.toLowerCase();
|
|
// Try to find via alias → then look it up in the map values
|
|
const monacoLang = LANGUAGE_ALIASES[lower];
|
|
if (!monacoLang) return lower;
|
|
|
|
// Find a matching entry in the map
|
|
for (const ids of Object.values(LANGUAGE_MAP)) {
|
|
if (ids.monaco === monacoLang) return ids.lowlight;
|
|
}
|
|
return lower;
|
|
}
|