From 17a7c824b848240c777469ff670a1189445ba5bd Mon Sep 17 00:00:00 2001 From: Andre van Tonder Date: Fri, 15 Aug 2025 21:18:27 +1000 Subject: [PATCH] Add Vue LSP and enable eslint for `.vue` files. (#1952) --- packages/opencode/src/lsp/language.ts | 1 + packages/opencode/src/lsp/server.ts | 63 ++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/lsp/language.ts b/packages/opencode/src/lsp/language.ts index 61686bd9..ccba0183 100644 --- a/packages/opencode/src/lsp/language.ts +++ b/packages/opencode/src/lsp/language.ts @@ -94,6 +94,7 @@ export const LANGUAGE_EXTENSIONS: Record = { ".yml": "yaml", ".mjs": "javascript", ".cjs": "javascript", + ".vue": "vue", ".zig": "zig", ".zon": "zig", } as const diff --git a/packages/opencode/src/lsp/server.ts b/packages/opencode/src/lsp/server.ts index 0a3954cf..ca462f7f 100644 --- a/packages/opencode/src/lsp/server.ts +++ b/packages/opencode/src/lsp/server.ts @@ -65,6 +65,67 @@ export namespace LSPServer { }, } + export const Vue: Info = { + id: "vue", + extensions: [".vue"], + root: NearestRoot([ + "tsconfig.json", + "jsconfig.json", + "package.json", + "pnpm-lock.yaml", + "yarn.lock", + "bun.lockb", + "bun.lock", + "vite.config.ts", + "vite.config.js", + "nuxt.config.ts", + "nuxt.config.js", + "vue.config.js", + ]), + async spawn(_, root) { + let binary = Bun.which("vue-language-server") + const args: string[] = [] + if (!binary) { + const js = path.join( + Global.Path.bin, + "node_modules", + "@vue", + "language-server", + "bin", + "vue-language-server.js", + ) + if (!(await Bun.file(js).exists())) { + await Bun.spawn([BunProc.which(), "install", "@vue/language-server"], { + cwd: Global.Path.bin, + env: { + ...process.env, + BUN_BE_BUN: "1", + }, + stdout: "pipe", + stderr: "pipe", + stdin: "pipe", + }).exited + } + binary = BunProc.which() + args.push("run", js) + } + args.push("--stdio") + const proc = spawn(binary, args, { + cwd: root, + env: { + ...process.env, + BUN_BE_BUN: "1", + }, + }) + return { + process: proc, + initialization: { + // Leave empty; the server will auto-detect workspace TypeScript. + }, + } + }, + } + export const ESLint: Info = { id: "eslint", root: NearestRoot([ @@ -81,7 +142,7 @@ export namespace LSPServer { ".eslintrc.json", "package.json", ]), - extensions: [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"], + extensions: [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts", ".vue"], async spawn(app, root) { const eslint = await Bun.resolve("eslint", app.path.cwd).catch(() => {}) if (!eslint) return