/** * CodeMirror 语言包加载器(动态导入,按需加载) */ import { getCmLanguage } from './languageMap' const languageCache = new Map() /** * 获取语言扩展(异步,首次调用会动态加载对应语言包) * @param {string} language - 语言名称 * @returns {Promise} CodeMirror 语言扩展 */ export async function loadLanguageExtension(language) { if (languageCache.has(language)) { return languageCache.get(language) } let mod, extension = null switch (language) { case 'javascript': mod = await import('@codemirror/lang-javascript') extension = mod.javascript({ jsx: true }) break case 'typescript': mod = await import('@codemirror/lang-javascript') extension = mod.javascript({ typescript: true, jsx: true }) break case 'json': ;({ json: extension } = await import('@codemirror/lang-json')) extension = extension() break case 'yaml': ;({ yaml: extension } = await import('@codemirror/lang-yaml')) extension = extension() break case 'html': ;({ html: extension } = await import('@codemirror/lang-html')) extension = extension() break case 'css': ;({ css: extension } = await import('@codemirror/lang-css')) extension = extension() break case 'cpp': case 'c': ;({ cpp: extension } = await import('@codemirror/lang-cpp')) extension = extension() break case 'rust': ;({ rust: extension } = await import('@codemirror/lang-rust')) extension = extension() break case 'go': ;({ go: extension } = await import('@codemirror/lang-go')) extension = extension() break case 'python': ;({ python: extension } = await import('@codemirror/lang-python')) extension = extension() break case 'php': ;({ php: extension } = await import('@codemirror/lang-php')) extension = extension() break case 'sql': ;({ sql: extension } = await import('@codemirror/lang-sql')) extension = extension() break case 'markdown': ;({ markdown: extension } = await import('@codemirror/lang-markdown')) extension = extension() break case 'java': ;({ java: extension } = await import('@codemirror/lang-java')) extension = extension() break case 'shell': case 'bash': case 'sh': case 'dockerfile': { const { StreamLanguage, shell } = await import('@codemirror/legacy-modes/mode/shell') extension = StreamLanguage.define(shell) break } case 'powershell': { const { StreamLanguage, powerShell } = await import('@codemirror/legacy-modes/mode/powershell') extension = StreamLanguage.define(powerShell) break } case 'batch': { // 自写 DOS batch 流式模式:REM/:: 整行注释,%var% 变量,常用关键字 const { StreamLanguage } = await import('@codemirror/language') const batchKeywords = new Set('echo off on set setlocal endlocal enabledelayedexpansion if not exist defined equ neq lss leq gtr geq for in do goto call exit exitb start del erase copy move ren rename md mkdir rd rmdir cd chdir type cls pause shift errorlevel title ver vol prompt pushd popd xcopy robocopy powershell cmd'.split(' ')) extension = StreamLanguage.define({ name: 'batch', token(stream) { if (stream.sol()) { stream.eatSpace() // 行首 REM(大小写不敏感)或 :: 开头的整行注释;:标签名 视作 keyword if (stream.match(/^rem(?:\s|$)/i) || stream.match(/^::/)) { stream.skipToEnd() return 'comment' } if (stream.match(/^:[\w.-]+/)) return 'keyword' } if (stream.eatSpace()) return null if (stream.match(/^"(?:[^"\r\n]|"")*"?/)) return 'string' if (stream.eat('^')) return 'operator' // !var! 延迟变量、%var% 环境变量、%~d0 类批处理参数 if (stream.match(/^!\w+!/) || stream.match(/^%\w+%/) || stream.match(/^%~[a-z]*[\d*]/i)) return 'atom' if (stream.match(/^\w+/)) { return batchKeywords.has(stream.current().toLowerCase()) ? 'keyword' : null } stream.next() return null } }) break } case 'dart': { const { StreamLanguage, clike: dart } = await import('@codemirror/legacy-modes/mode/clike') extension = StreamLanguage.define(dart) break } default: return null } if (extension) { languageCache.set(language, extension) } return extension } /** * 根据文件扩展名获取语言名称 * @param {string} extension - 文件扩展名 * @returns {string} 语言名称 */ export function getLanguageFromExtension(extension) { return getCmLanguage(extension) }