-- nvim-lint: Linting support (replaces none-ls diagnostics) -- none-ls removed ESLint and many linters, so we use nvim-lint instead return { "mfussenegger/nvim-lint", event = { "BufReadPre", "BufNewFile" }, config = function() local lint = require("lint") -- Configure linters per filetype lint.linters_by_ft = { javascript = { "eslint_d" }, javascriptreact = { "eslint_d" }, typescript = { "eslint_d" }, typescriptreact = { "eslint_d" }, markdown = { "markdownlint" }, php = { "phpcs" }, -- Python: ruff LSP handles linting } -- Helper: Find project-local executable, fallback to global local function find_executable(names) local cwd = vim.fn.getcwd() local mason_bin = vim.fn.stdpath("data") .. "/mason/bin/" local search_paths = { cwd .. "/node_modules/.bin/", cwd .. "/vendor/bin/", mason_bin, } for _, name in ipairs(names) do for _, path in ipairs(search_paths) do local full_path = path .. name if vim.fn.executable(full_path) == 1 then return full_path end end if vim.fn.executable(name) == 1 then return name end end return nil end -- Configure phpcs for WordPress standards lint.linters.phpcs.cmd = find_executable({ "phpcs" }) or "phpcs" lint.linters.phpcs.args = { "-q", "--report=json", function() local phpcs_xml = vim.fn.findfile("phpcs.xml", ".;") if phpcs_xml == "" then phpcs_xml = vim.fn.findfile("phpcs.xml.dist", ".;") end if phpcs_xml == "" then return "--standard=WordPress" end return nil end, "-", -- stdin } -- Configure eslint_d to use project-local first lint.linters.eslint_d.cmd = find_executable({ "eslint_d", "eslint" }) or "eslint_d" -- Note: ~/.eslintrc.json serves as global fallback when no project config exists -- Configure markdownlint lint.linters.markdownlint.cmd = find_executable({ "markdownlint" }) or "markdownlint" -- Auto-lint on these events local lint_augroup = vim.api.nvim_create_augroup("lint", { clear = true }) vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost", "InsertLeave" }, { group = lint_augroup, callback = function() lint.try_lint() end, }) end, }