refactor(nvim): simplify lazy loading configuration
This commit is contained in:
1 parent
8c7f943e64
commit
2c1e70cfdc
7 files changed
+1063
-1
No files matched your search
@@ -19,6 +19,7 @@
|
|||||||
"conform.nvim": { "branch": "master", "commit": "fbcb4fa7f34bfea9be702ffff481a8e336ebf6ed" },
|
"conform.nvim": { "branch": "master", "commit": "fbcb4fa7f34bfea9be702ffff481a8e336ebf6ed" },
|
||||||
"cyberdream.nvim": { "branch": "main", "commit": "eba11f590026e74915e13d12a53cdbdc9b98d9f9" },
|
"cyberdream.nvim": { "branch": "main", "commit": "eba11f590026e74915e13d12a53cdbdc9b98d9f9" },
|
||||||
"deno-nvim": { "branch": "master", "commit": "5c1ef9762f916033bd3b9b37878384cae24ddb4e" },
|
"deno-nvim": { "branch": "master", "commit": "5c1ef9762f916033bd3b9b37878384cae24ddb4e" },
|
||||||
|
"doodle": { "branch": "main", "commit": "2f192d6ec821f9ae14460689047438aae8002ec9" },
|
||||||
"dressing.nvim": { "branch": "master", "commit": "3a45525bb182730fe462325c99395529308f431e" },
|
"dressing.nvim": { "branch": "master", "commit": "3a45525bb182730fe462325c99395529308f431e" },
|
||||||
"friendly-snippets": { "branch": "main", "commit": "efff286dd74c22f731cdec26a70b46e5b203c619" },
|
"friendly-snippets": { "branch": "main", "commit": "efff286dd74c22f731cdec26a70b46e5b203c619" },
|
||||||
"gitsigns.nvim": { "branch": "main", "commit": "7010000889bfb6c26065e0b0f7f1e6aa9163edd9" },
|
"gitsigns.nvim": { "branch": "main", "commit": "7010000889bfb6c26065e0b0f7f1e6aa9163edd9" },
|
||||||
@@ -65,6 +66,7 @@
|
|||||||
"resession.nvim": { "branch": "master", "commit": "cc819b0489938d03e4f3532a583354f0287c015b" },
|
"resession.nvim": { "branch": "master", "commit": "cc819b0489938d03e4f3532a583354f0287c015b" },
|
||||||
"schemastore.nvim": { "branch": "main", "commit": "667eaa5da8f66f1dd97c905a12dd1eb544a2d259" },
|
"schemastore.nvim": { "branch": "main", "commit": "667eaa5da8f66f1dd97c905a12dd1eb544a2d259" },
|
||||||
"smart-splits.nvim": { "branch": "master", "commit": "ddb23c1a1cf1507bda487cda7f6e4690965ef9f5" },
|
"smart-splits.nvim": { "branch": "master", "commit": "ddb23c1a1cf1507bda487cda7f6e4690965ef9f5" },
|
||||||
|
"sqlite.lua": { "branch": "master", "commit": "50092d60feb242602d7578398c6eb53b4a8ffe7b" },
|
||||||
"supermaven-nvim": { "branch": "main", "commit": "07d20fce48a5629686aefb0a7cd4b25e33947d50" },
|
"supermaven-nvim": { "branch": "main", "commit": "07d20fce48a5629686aefb0a7cd4b25e33947d50" },
|
||||||
"telescope-fzf-native.nvim": { "branch": "main", "commit": "1f08ed60cafc8f6168b72b80be2b2ea149813e55" },
|
"telescope-fzf-native.nvim": { "branch": "main", "commit": "1f08ed60cafc8f6168b72b80be2b2ea149813e55" },
|
||||||
"telescope.nvim": { "branch": "master", "commit": "a17d611a0e111836a1db5295f04945df407c5135" },
|
"telescope.nvim": { "branch": "master", "commit": "a17d611a0e111836a1db5295f04945df407c5135" },
|
||||||
|
|||||||
@@ -0,0 +1,281 @@
|
|||||||
|
--- Build tools and development environment optimizations
|
||||||
|
--- Includes support for bun, vite, and modern JS tooling
|
||||||
|
--- @module plugins.buildtools
|
||||||
|
|
||||||
|
return {
|
||||||
|
-- Vim support for various config files
|
||||||
|
{
|
||||||
|
"nvim-treesitter/nvim-treesitter",
|
||||||
|
optional = true,
|
||||||
|
opts = function(_, opts)
|
||||||
|
if opts.ensure_installed ~= "all" then
|
||||||
|
opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, {
|
||||||
|
"toml",
|
||||||
|
"yaml",
|
||||||
|
"json",
|
||||||
|
"jsonc",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Enhanced JSON support with schema validation
|
||||||
|
{
|
||||||
|
"b0o/schemastore.nvim",
|
||||||
|
lazy = true,
|
||||||
|
dependencies = {
|
||||||
|
{
|
||||||
|
"AstroNvim/astrolsp",
|
||||||
|
optional = true,
|
||||||
|
---@type AstroLSPOpts
|
||||||
|
opts = {
|
||||||
|
---@diagnostic disable: missing-fields
|
||||||
|
config = {
|
||||||
|
jsonls = {
|
||||||
|
on_new_config = function(config)
|
||||||
|
if not config.settings.json then config.settings.json = {} end
|
||||||
|
if not config.settings.json.schemas then config.settings.json.schemas = {} end
|
||||||
|
vim.list_extend(config.settings.json.schemas, require("schemastore").json.schemas())
|
||||||
|
end,
|
||||||
|
settings = {
|
||||||
|
json = {
|
||||||
|
format = { enable = true },
|
||||||
|
validate = { enable = true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- YAML schema support
|
||||||
|
{
|
||||||
|
"AstroNvim/astrolsp",
|
||||||
|
optional = true,
|
||||||
|
---@type AstroLSPOpts
|
||||||
|
opts = {
|
||||||
|
---@diagnostic disable: missing-fields
|
||||||
|
config = {
|
||||||
|
yamlls = {
|
||||||
|
on_new_config = function(config)
|
||||||
|
config.settings.yaml.schemas = vim.tbl_deep_extend(
|
||||||
|
"force",
|
||||||
|
config.settings.yaml.schemas or {},
|
||||||
|
require("schemastore").yaml.schemas()
|
||||||
|
)
|
||||||
|
end,
|
||||||
|
settings = {
|
||||||
|
yaml = {
|
||||||
|
schemaStore = {
|
||||||
|
enable = false,
|
||||||
|
url = "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Task runner integration (for vite, bun scripts)
|
||||||
|
{
|
||||||
|
"stevearc/overseer.nvim",
|
||||||
|
cmd = {
|
||||||
|
"OverseerRun",
|
||||||
|
"OverseerToggle",
|
||||||
|
"OverseerOpen",
|
||||||
|
"OverseerClose",
|
||||||
|
"OverseerLoadBundle",
|
||||||
|
"OverseerSaveBundle",
|
||||||
|
"OverseerDeleteBundle",
|
||||||
|
"OverseerRunCmd",
|
||||||
|
"OverseerQuickAction",
|
||||||
|
"OverseerTaskAction",
|
||||||
|
},
|
||||||
|
opts = {
|
||||||
|
strategy = {
|
||||||
|
"toggleterm",
|
||||||
|
direction = "horizontal",
|
||||||
|
open_on_start = false,
|
||||||
|
},
|
||||||
|
templates = {
|
||||||
|
"builtin",
|
||||||
|
"bun.run",
|
||||||
|
"npm.run",
|
||||||
|
"vite.dev",
|
||||||
|
"vite.build",
|
||||||
|
},
|
||||||
|
task_list = {
|
||||||
|
bindings = {
|
||||||
|
["<C-l>"] = false,
|
||||||
|
["<C-h>"] = false,
|
||||||
|
["<C-k>"] = false,
|
||||||
|
["<C-j>"] = false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
config = function(_, opts)
|
||||||
|
local overseer = require "overseer"
|
||||||
|
overseer.setup(opts)
|
||||||
|
|
||||||
|
-- Custom task templates for bun
|
||||||
|
overseer.register_template {
|
||||||
|
name = "bun.run",
|
||||||
|
builder = function(params)
|
||||||
|
return {
|
||||||
|
cmd = { "bun" },
|
||||||
|
args = { "run", params.script },
|
||||||
|
name = "bun run " .. params.script,
|
||||||
|
components = { "default" },
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
params = {
|
||||||
|
script = {
|
||||||
|
type = "string",
|
||||||
|
default = "dev",
|
||||||
|
description = "Script to run from package.json",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
condition = {
|
||||||
|
filetype = { "typescript", "javascript", "typescriptreact", "javascriptreact" },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Custom task templates for vite
|
||||||
|
overseer.register_template {
|
||||||
|
name = "vite.dev",
|
||||||
|
builder = function()
|
||||||
|
return {
|
||||||
|
cmd = { "bun" },
|
||||||
|
args = { "run", "dev" },
|
||||||
|
name = "vite dev server",
|
||||||
|
components = {
|
||||||
|
{ "on_output_quickfix", open = false },
|
||||||
|
"default",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
condition = {
|
||||||
|
callback = function()
|
||||||
|
return vim.fn.filereadable "vite.config.ts" == 1 or vim.fn.filereadable "vite.config.js" == 1
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
overseer.register_template {
|
||||||
|
name = "vite.build",
|
||||||
|
builder = function()
|
||||||
|
return {
|
||||||
|
cmd = { "bun" },
|
||||||
|
args = { "run", "build" },
|
||||||
|
name = "vite build",
|
||||||
|
components = {
|
||||||
|
{ "on_output_quickfix", open = true },
|
||||||
|
"default",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
condition = {
|
||||||
|
callback = function()
|
||||||
|
return vim.fn.filereadable "vite.config.ts" == 1 or vim.fn.filereadable "vite.config.js" == 1
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- REST client for testing Workers/APIs
|
||||||
|
{
|
||||||
|
"rest-nvim/rest.nvim",
|
||||||
|
ft = "http",
|
||||||
|
dependencies = { "nvim-lua/plenary.nvim" },
|
||||||
|
opts = {
|
||||||
|
result_split_horizontal = false,
|
||||||
|
skip_ssl_verification = false,
|
||||||
|
encode_url = true,
|
||||||
|
highlight = {
|
||||||
|
enabled = true,
|
||||||
|
timeout = 150,
|
||||||
|
},
|
||||||
|
result = {
|
||||||
|
show_url = true,
|
||||||
|
show_curl_command = true,
|
||||||
|
show_http_info = true,
|
||||||
|
show_headers = true,
|
||||||
|
},
|
||||||
|
jump_to_request = false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Seamless navigation between build errors
|
||||||
|
{
|
||||||
|
"folke/trouble.nvim",
|
||||||
|
cmd = { "Trouble", "TroubleToggle" },
|
||||||
|
opts = {
|
||||||
|
use_diagnostic_signs = true,
|
||||||
|
action_keys = {
|
||||||
|
close = "q",
|
||||||
|
cancel = "<esc>",
|
||||||
|
refresh = "r",
|
||||||
|
jump = { "<cr>", "<tab>" },
|
||||||
|
open_split = { "<c-x>" },
|
||||||
|
open_vsplit = { "<c-v>" },
|
||||||
|
open_tab = { "<c-t>" },
|
||||||
|
jump_close = { "o" },
|
||||||
|
toggle_mode = "m",
|
||||||
|
toggle_preview = "P",
|
||||||
|
hover = "K",
|
||||||
|
preview = "p",
|
||||||
|
close_folds = { "zM", "zm" },
|
||||||
|
open_folds = { "zR", "zr" },
|
||||||
|
toggle_fold = { "zA", "za" },
|
||||||
|
previous = "k",
|
||||||
|
next = "j",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Git integration for collaborative development
|
||||||
|
{
|
||||||
|
"lewis6991/gitsigns.nvim",
|
||||||
|
event = "User AstroGitFile",
|
||||||
|
opts = {
|
||||||
|
signs = {
|
||||||
|
add = { text = "▎" },
|
||||||
|
change = { text = "▎" },
|
||||||
|
delete = { text = "" },
|
||||||
|
topdelete = { text = "" },
|
||||||
|
changedelete = { text = "▎" },
|
||||||
|
untracked = { text = "▎" },
|
||||||
|
},
|
||||||
|
current_line_blame = false,
|
||||||
|
current_line_blame_opts = {
|
||||||
|
virt_text = true,
|
||||||
|
virt_text_pos = "eol",
|
||||||
|
delay = 300,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- EditorConfig support
|
||||||
|
{
|
||||||
|
"editorconfig/editorconfig-vim",
|
||||||
|
event = { "BufReadPre", "BufNewFile" },
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Development container support
|
||||||
|
{
|
||||||
|
"esensar/nvim-dev-container",
|
||||||
|
dependencies = { "nvim-treesitter/nvim-treesitter" },
|
||||||
|
cmd = {
|
||||||
|
"DevcontainerStart",
|
||||||
|
"DevcontainerAttach",
|
||||||
|
"DevcontainerExec",
|
||||||
|
"DevcontainerStop",
|
||||||
|
"DevcontainerLogs",
|
||||||
|
},
|
||||||
|
opts = {},
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,293 @@
|
|||||||
|
--- Cloudflare Workers and React/shadcn development tools
|
||||||
|
--- Includes Workers-specific LSP, React tooling, and UI helpers
|
||||||
|
--- @module plugins.cloudflare
|
||||||
|
|
||||||
|
return {
|
||||||
|
-- WASM/WebAssembly support for Workers
|
||||||
|
{
|
||||||
|
"nvim-treesitter/nvim-treesitter",
|
||||||
|
optional = true,
|
||||||
|
opts = function(_, opts)
|
||||||
|
if opts.ensure_installed ~= "all" then
|
||||||
|
opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, {
|
||||||
|
"wgsl",
|
||||||
|
"wgsl_bevy",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- TOML support for wrangler.toml
|
||||||
|
{
|
||||||
|
"AstroNvim/astrolsp",
|
||||||
|
optional = true,
|
||||||
|
---@type AstroLSPOpts
|
||||||
|
opts = {
|
||||||
|
---@diagnostic disable: missing-fields
|
||||||
|
config = {
|
||||||
|
taplo = {
|
||||||
|
settings = {
|
||||||
|
evenBetterToml = {
|
||||||
|
schema = {
|
||||||
|
enabled = true,
|
||||||
|
associations = {
|
||||||
|
["wrangler\\.toml"] = "https://raw.githubusercontent.com/cloudflare/workers-sdk/main/schemas/wrangler.json",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Enhanced search/replace for refactoring React components
|
||||||
|
{
|
||||||
|
"nvim-pack/nvim-spectre",
|
||||||
|
cmd = "Spectre",
|
||||||
|
dependencies = { "nvim-lua/plenary.nvim" },
|
||||||
|
opts = {
|
||||||
|
mapping = {
|
||||||
|
["toggle_line"] = {
|
||||||
|
map = "dd",
|
||||||
|
cmd = "<cmd>lua require('spectre').toggle_line()<CR>",
|
||||||
|
desc = "toggle item",
|
||||||
|
},
|
||||||
|
["enter_file"] = {
|
||||||
|
map = "<cr>",
|
||||||
|
cmd = "<cmd>lua require('spectre.actions').select_entry()<CR>",
|
||||||
|
desc = "open file",
|
||||||
|
},
|
||||||
|
["send_to_qf"] = {
|
||||||
|
map = "<leader>q",
|
||||||
|
cmd = "<cmd>lua require('spectre.actions').send_to_qf()<CR>",
|
||||||
|
desc = "send all items to quickfix",
|
||||||
|
},
|
||||||
|
["replace_cmd"] = {
|
||||||
|
map = "<leader>c",
|
||||||
|
cmd = "<cmd>lua require('spectre.actions').replace_cmd()<CR>",
|
||||||
|
desc = "input replace command",
|
||||||
|
},
|
||||||
|
["show_option_menu"] = {
|
||||||
|
map = "<leader>o",
|
||||||
|
cmd = "<cmd>lua require('spectre').show_options()<CR>",
|
||||||
|
desc = "show options",
|
||||||
|
},
|
||||||
|
["run_current_replace"] = {
|
||||||
|
map = "<leader>rc",
|
||||||
|
cmd = "<cmd>lua require('spectre.actions').run_current_replace()<CR>",
|
||||||
|
desc = "replace current line",
|
||||||
|
},
|
||||||
|
["run_replace"] = {
|
||||||
|
map = "<leader>R",
|
||||||
|
cmd = "<cmd>lua require('spectre.actions').run_replace()<CR>",
|
||||||
|
desc = "replace all",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- React component preview and development
|
||||||
|
{
|
||||||
|
"roobert/tailwindcss-colorizer-cmp.nvim",
|
||||||
|
event = "VeryLazy",
|
||||||
|
opts = {
|
||||||
|
color_square_width = 2,
|
||||||
|
},
|
||||||
|
config = function(_, opts)
|
||||||
|
require("tailwindcss-colorizer-cmp").setup(opts)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Color highlighting for CSS/Tailwind
|
||||||
|
{
|
||||||
|
"NvChad/nvim-colorizer.lua",
|
||||||
|
event = { "BufReadPost", "BufNewFile" },
|
||||||
|
opts = {
|
||||||
|
filetypes = {
|
||||||
|
"typescript",
|
||||||
|
"typescriptreact",
|
||||||
|
"javascript",
|
||||||
|
"javascriptreact",
|
||||||
|
"css",
|
||||||
|
"scss",
|
||||||
|
"html",
|
||||||
|
"vue",
|
||||||
|
"lua",
|
||||||
|
},
|
||||||
|
user_default_options = {
|
||||||
|
RGB = true,
|
||||||
|
RRGGBB = true,
|
||||||
|
names = false,
|
||||||
|
RRGGBBAA = true,
|
||||||
|
AARRGGBB = false,
|
||||||
|
rgb_fn = true,
|
||||||
|
hsl_fn = true,
|
||||||
|
css = true,
|
||||||
|
css_fn = true,
|
||||||
|
mode = "background",
|
||||||
|
tailwind = true,
|
||||||
|
sass = { enable = true, parsers = { "css" } },
|
||||||
|
virtualtext = "■",
|
||||||
|
always_update = false,
|
||||||
|
},
|
||||||
|
buftypes = {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Import cost for monitoring bundle size
|
||||||
|
{
|
||||||
|
"yardnsm/vim-import-cost",
|
||||||
|
build = "npm install --production",
|
||||||
|
ft = { "javascript", "typescript", "javascriptreact", "typescriptreact" },
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Live browser reload for Workers development
|
||||||
|
{
|
||||||
|
"Barrett17/browser-sync.nvim",
|
||||||
|
build = "npm install -g browser-sync",
|
||||||
|
cmd = {
|
||||||
|
"BrowserSyncStart",
|
||||||
|
"BrowserSyncReload",
|
||||||
|
"BrowserSyncStop",
|
||||||
|
},
|
||||||
|
opts = {},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Component generator for shadcn/ui
|
||||||
|
{
|
||||||
|
"chrisgrieser/nvim-scissors",
|
||||||
|
dependencies = { "nvim-telescope/telescope.nvim" },
|
||||||
|
cmd = { "ScissorsAddNewSnippet", "ScissorsEditSnippet" },
|
||||||
|
opts = {
|
||||||
|
snippetDir = vim.fn.stdpath "config" .. "/snippets",
|
||||||
|
editSnippetPopup = {
|
||||||
|
height = 0.4,
|
||||||
|
width = 0.6,
|
||||||
|
border = "rounded",
|
||||||
|
keymaps = {
|
||||||
|
cancel = "q",
|
||||||
|
saveChanges = "<CR>",
|
||||||
|
deleteSnippet = "<leader>d",
|
||||||
|
duplicateSnippet = "<leader>c",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- HTTP client for testing Workers
|
||||||
|
{
|
||||||
|
"mistweaverco/kulala.nvim",
|
||||||
|
ft = "http",
|
||||||
|
opts = {
|
||||||
|
default_view = "body",
|
||||||
|
debug = false,
|
||||||
|
contenttypes = {
|
||||||
|
["application/json"] = {
|
||||||
|
ft = "json",
|
||||||
|
formatter = { "jq", "." },
|
||||||
|
},
|
||||||
|
["application/xml"] = {
|
||||||
|
ft = "xml",
|
||||||
|
formatter = { "xmllint", "--format", "-" },
|
||||||
|
},
|
||||||
|
["text/html"] = {
|
||||||
|
ft = "html",
|
||||||
|
formatter = { "xmllint", "--format", "--html", "-" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Enhanced movement for JSX/TSX
|
||||||
|
{
|
||||||
|
"echasnovski/mini.ai",
|
||||||
|
event = { "BufReadPost", "BufNewFile" },
|
||||||
|
opts = function()
|
||||||
|
local ai = require "mini.ai"
|
||||||
|
return {
|
||||||
|
custom_textobjects = {
|
||||||
|
-- Function calls
|
||||||
|
f = ai.gen_spec.treesitter { a = "@call.outer", i = "@call.inner" },
|
||||||
|
-- Function definitions
|
||||||
|
F = ai.gen_spec.treesitter { a = "@function.outer", i = "@function.inner" },
|
||||||
|
-- Classes
|
||||||
|
c = ai.gen_spec.treesitter { a = "@class.outer", i = "@class.inner" },
|
||||||
|
-- Parameters/arguments
|
||||||
|
a = ai.gen_spec.treesitter { a = "@parameter.outer", i = "@parameter.inner" },
|
||||||
|
-- JSX elements
|
||||||
|
x = ai.gen_spec.treesitter {
|
||||||
|
a = { "@jsx_element", "@jsx_self_closing_element" },
|
||||||
|
i = { "@jsx_element", "@jsx_self_closing_element" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- React component navigation
|
||||||
|
{
|
||||||
|
"someone-stole-my-name/yaml-companion.nvim",
|
||||||
|
ft = { "yaml" },
|
||||||
|
dependencies = {
|
||||||
|
{ "neovim/nvim-lspconfig" },
|
||||||
|
{ "nvim-lua/plenary.nvim" },
|
||||||
|
{ "nvim-telescope/telescope.nvim" },
|
||||||
|
},
|
||||||
|
opts = {},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Worker-specific terminal commands via toggleterm
|
||||||
|
{
|
||||||
|
"akinsho/toggleterm.nvim",
|
||||||
|
optional = true,
|
||||||
|
opts = function(_, opts)
|
||||||
|
local Terminal = require("toggleterm.terminal").Terminal
|
||||||
|
|
||||||
|
-- Wrangler dev server
|
||||||
|
local wrangler_dev = Terminal:new {
|
||||||
|
cmd = "bunx wrangler dev",
|
||||||
|
hidden = true,
|
||||||
|
direction = "float",
|
||||||
|
float_opts = {
|
||||||
|
border = "curved",
|
||||||
|
},
|
||||||
|
on_open = function(term)
|
||||||
|
vim.cmd "startinsert!"
|
||||||
|
vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "<cmd>close<CR>", { noremap = true, silent = true })
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Wrangler tail (logs)
|
||||||
|
local wrangler_tail = Terminal:new {
|
||||||
|
cmd = "bunx wrangler tail",
|
||||||
|
hidden = true,
|
||||||
|
direction = "horizontal",
|
||||||
|
on_open = function(term)
|
||||||
|
vim.cmd "startinsert!"
|
||||||
|
vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "<cmd>close<CR>", { noremap = true, silent = true })
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Wrangler deploy
|
||||||
|
local wrangler_deploy = Terminal:new {
|
||||||
|
cmd = "bunx wrangler deploy",
|
||||||
|
hidden = true,
|
||||||
|
direction = "float",
|
||||||
|
close_on_exit = false,
|
||||||
|
on_open = function(term)
|
||||||
|
vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "<cmd>close<CR>", { noremap = true, silent = true })
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Extend the opts with custom terminals
|
||||||
|
opts.on_create = function()
|
||||||
|
vim.keymap.set("n", "<leader>wd", function() wrangler_dev:toggle() end, { desc = "Wrangler Dev" })
|
||||||
|
vim.keymap.set("n", "<leader>wt", function() wrangler_tail:toggle() end, { desc = "Wrangler Tail" })
|
||||||
|
vim.keymap.set("n", "<leader>wp", function() wrangler_deploy:toggle() end, { desc = "Wrangler Deploy" })
|
||||||
|
end
|
||||||
|
|
||||||
|
return opts
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
--- Linting and formatting configuration
|
||||||
|
--- Includes oxlint, prettier, and ESLint integration
|
||||||
|
--- @module plugins.linting
|
||||||
|
|
||||||
|
return {
|
||||||
|
-- Conform for formatting
|
||||||
|
{
|
||||||
|
"stevearc/conform.nvim",
|
||||||
|
event = "BufWritePre",
|
||||||
|
cmd = { "ConformInfo" },
|
||||||
|
opts = {
|
||||||
|
formatters_by_ft = {
|
||||||
|
typescript = { "prettier" },
|
||||||
|
typescriptreact = { "prettier" },
|
||||||
|
javascript = { "prettier" },
|
||||||
|
javascriptreact = { "prettier" },
|
||||||
|
json = { "prettier" },
|
||||||
|
jsonc = { "prettier" },
|
||||||
|
css = { "prettier" },
|
||||||
|
scss = { "prettier" },
|
||||||
|
html = { "prettier" },
|
||||||
|
markdown = { "prettier" },
|
||||||
|
yaml = { "prettier" },
|
||||||
|
lua = { "stylua" },
|
||||||
|
rust = { "rustfmt" },
|
||||||
|
toml = { "taplo" },
|
||||||
|
},
|
||||||
|
format_on_save = function(bufnr)
|
||||||
|
-- Disable with a global or buffer-local variable
|
||||||
|
if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then return end
|
||||||
|
return {
|
||||||
|
timeout_ms = 500,
|
||||||
|
lsp_fallback = true,
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
formatters = {
|
||||||
|
prettier = {
|
||||||
|
prepend_args = {
|
||||||
|
"--plugin=prettier-plugin-tailwindcss",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
config = function(_, opts)
|
||||||
|
require("conform").setup(opts)
|
||||||
|
|
||||||
|
-- Command to toggle format on save
|
||||||
|
vim.api.nvim_create_user_command("FormatToggle", function(args)
|
||||||
|
if args.bang then
|
||||||
|
-- Toggle buffer-local setting
|
||||||
|
vim.b.disable_autoformat = not vim.b.disable_autoformat
|
||||||
|
else
|
||||||
|
-- Toggle global setting
|
||||||
|
vim.g.disable_autoformat = not vim.g.disable_autoformat
|
||||||
|
end
|
||||||
|
local status = vim.g.disable_autoformat and "disabled" or "enabled"
|
||||||
|
vim.notify("Format on save " .. status, vim.log.levels.INFO)
|
||||||
|
end, {
|
||||||
|
desc = "Toggle format on save",
|
||||||
|
bang = true,
|
||||||
|
})
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Lint with nvim-lint (oxlint integration)
|
||||||
|
{
|
||||||
|
"mfussenegger/nvim-lint",
|
||||||
|
event = { "BufReadPre", "BufNewFile" },
|
||||||
|
config = function()
|
||||||
|
local lint = require "lint"
|
||||||
|
|
||||||
|
-- Configure oxlint for TypeScript/JavaScript
|
||||||
|
lint.linters.oxlint = {
|
||||||
|
cmd = "oxlint",
|
||||||
|
stdin = false,
|
||||||
|
args = {
|
||||||
|
"--format=json",
|
||||||
|
},
|
||||||
|
stream = "stdout",
|
||||||
|
ignore_exitcode = true,
|
||||||
|
parser = function(output)
|
||||||
|
if output == "" or output == nil then return {} end
|
||||||
|
|
||||||
|
local ok, decoded = pcall(vim.fn.json_decode, output)
|
||||||
|
if not ok then return {} end
|
||||||
|
|
||||||
|
local diagnostics = {}
|
||||||
|
for _, item in ipairs(decoded) do
|
||||||
|
if item.diagnostics then
|
||||||
|
for _, diagnostic in ipairs(item.diagnostics) do
|
||||||
|
table.insert(diagnostics, {
|
||||||
|
lnum = diagnostic.start.line - 1,
|
||||||
|
end_lnum = diagnostic["end"].line - 1,
|
||||||
|
col = diagnostic.start.column - 1,
|
||||||
|
end_col = diagnostic["end"].column - 1,
|
||||||
|
severity = vim.diagnostic.severity.WARN,
|
||||||
|
source = "oxlint",
|
||||||
|
message = diagnostic.message,
|
||||||
|
code = diagnostic.rule_id,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return diagnostics
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Configure linters per filetype
|
||||||
|
lint.linters_by_ft = {
|
||||||
|
typescript = { "oxlint" },
|
||||||
|
typescriptreact = { "oxlint" },
|
||||||
|
javascript = { "oxlint" },
|
||||||
|
javascriptreact = { "oxlint" },
|
||||||
|
css = { "stylelint" },
|
||||||
|
scss = { "stylelint" },
|
||||||
|
markdown = { "markdownlint" },
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Auto-lint on save and text changed
|
||||||
|
local lint_augroup = vim.api.nvim_create_augroup("lint", { clear = true })
|
||||||
|
vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost", "InsertLeave", "TextChanged" }, {
|
||||||
|
group = lint_augroup,
|
||||||
|
callback = function()
|
||||||
|
-- Only lint if file exists on disk
|
||||||
|
if vim.fn.filereadable(vim.api.nvim_buf_get_name(0)) == 1 then lint.try_lint() end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Mason tool installer for linters/formatters
|
||||||
|
{
|
||||||
|
"WhoIsSethDaniel/mason-tool-installer.nvim",
|
||||||
|
dependencies = { "williamboman/mason.nvim" },
|
||||||
|
cmd = { "MasonToolsInstall", "MasonToolsUpdate" },
|
||||||
|
opts = {
|
||||||
|
ensure_installed = {
|
||||||
|
-- Formatters
|
||||||
|
"prettier",
|
||||||
|
"stylua",
|
||||||
|
"rustfmt",
|
||||||
|
"taplo",
|
||||||
|
-- Linters
|
||||||
|
"eslint_d",
|
||||||
|
"stylelint",
|
||||||
|
"markdownlint",
|
||||||
|
-- Note: oxlint should be installed via cargo/npm separately
|
||||||
|
},
|
||||||
|
auto_update = false,
|
||||||
|
run_on_start = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Additional diagnostics UI
|
||||||
|
{
|
||||||
|
"folke/trouble.nvim",
|
||||||
|
optional = true,
|
||||||
|
opts = {
|
||||||
|
modes = {
|
||||||
|
lsp = {
|
||||||
|
win = { position = "right" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Inline linting hints
|
||||||
|
{
|
||||||
|
"https://git.sr.ht/~whynothugo/lsp_lines.nvim",
|
||||||
|
event = { "BufReadPost", "BufNewFile" },
|
||||||
|
config = function()
|
||||||
|
require("lsp_lines").setup()
|
||||||
|
-- Disable virtual_text since lsp_lines will show diagnostics
|
||||||
|
vim.diagnostic.config { virtual_text = false }
|
||||||
|
|
||||||
|
-- Toggle command
|
||||||
|
vim.api.nvim_create_user_command("LspLinesToggle", function()
|
||||||
|
local new_value = not require("lsp_lines").toggle()
|
||||||
|
vim.diagnostic.config { virtual_text = new_value }
|
||||||
|
end, { desc = "Toggle LSP lines" })
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Better quickfix for showing lint errors
|
||||||
|
{
|
||||||
|
"kevinhwang91/nvim-bqf",
|
||||||
|
ft = "qf",
|
||||||
|
opts = {
|
||||||
|
auto_resize_height = true,
|
||||||
|
func_map = {
|
||||||
|
vsplit = "v",
|
||||||
|
split = "s",
|
||||||
|
tab = "t",
|
||||||
|
tabb = "T",
|
||||||
|
tabc = "<C-t>",
|
||||||
|
ptogglemode = "z,",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
--- Telescope configuration with Doodle integration
|
||||||
|
--- Extends telescope.nvim with doodle extension
|
||||||
|
--- @module plugins.telescope
|
||||||
|
|
||||||
|
return {
|
||||||
|
"nvim-telescope/telescope.nvim",
|
||||||
|
dependencies = {
|
||||||
|
"nvim-lua/plenary.nvim",
|
||||||
|
"apdot/doodle",
|
||||||
|
},
|
||||||
|
opts = function(_, opts)
|
||||||
|
-- Ensure extensions table exists
|
||||||
|
opts.extensions = opts.extensions or {}
|
||||||
|
|
||||||
|
-- Add doodle extension configuration
|
||||||
|
opts.extensions.doodle = {}
|
||||||
|
|
||||||
|
return opts
|
||||||
|
end,
|
||||||
|
config = function(_, opts)
|
||||||
|
local telescope = require "telescope"
|
||||||
|
|
||||||
|
-- Setup telescope with options
|
||||||
|
telescope.setup(opts)
|
||||||
|
|
||||||
|
-- Load the doodle extension
|
||||||
|
telescope.load_extension "doodle"
|
||||||
|
end,
|
||||||
|
}
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
--- TypeScript/TSX development optimizations
|
||||||
|
--- Includes LSP, treesitter, linting, and React-specific tooling
|
||||||
|
--- @module plugins.tsx
|
||||||
|
|
||||||
|
return {
|
||||||
|
-- TypeScript LSP with enhanced settings for React/TSX
|
||||||
|
{
|
||||||
|
"AstroNvim/astrolsp",
|
||||||
|
optional = true,
|
||||||
|
---@type AstroLSPOpts
|
||||||
|
opts = {
|
||||||
|
---@diagnostic disable: missing-fields
|
||||||
|
config = {
|
||||||
|
-- TypeScript/JavaScript LSP
|
||||||
|
tsserver = {
|
||||||
|
settings = {
|
||||||
|
typescript = {
|
||||||
|
inlayHints = {
|
||||||
|
includeInlayParameterNameHints = "all",
|
||||||
|
includeInlayParameterNameHintsWhenArgumentMatchesName = true,
|
||||||
|
includeInlayFunctionParameterTypeHints = true,
|
||||||
|
includeInlayVariableTypeHints = true,
|
||||||
|
includeInlayVariableTypeHintsWhenTypeMatchesName = true,
|
||||||
|
includeInlayPropertyDeclarationTypeHints = true,
|
||||||
|
includeInlayFunctionLikeReturnTypeHints = true,
|
||||||
|
includeInlayEnumMemberValueHints = true,
|
||||||
|
},
|
||||||
|
suggest = {
|
||||||
|
includeCompletionsForModuleExports = true,
|
||||||
|
},
|
||||||
|
preferences = {
|
||||||
|
importModuleSpecifier = "relative",
|
||||||
|
jsxAttributeCompletionStyle = "auto",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
javascript = {
|
||||||
|
inlayHints = {
|
||||||
|
includeInlayParameterNameHints = "all",
|
||||||
|
includeInlayParameterNameHintsWhenArgumentMatchesName = true,
|
||||||
|
includeInlayFunctionParameterTypeHints = true,
|
||||||
|
includeInlayVariableTypeHints = true,
|
||||||
|
includeInlayPropertyDeclarationTypeHints = true,
|
||||||
|
includeInlayFunctionLikeReturnTypeHints = true,
|
||||||
|
includeInlayEnumMemberValueHints = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
-- Volar for Vue (also helpful for some React scenarios)
|
||||||
|
volar = {
|
||||||
|
filetypes = { "vue", "typescript", "javascript", "typescriptreact", "javascriptreact" },
|
||||||
|
},
|
||||||
|
-- Tailwind CSS LSP for shadcn/ui
|
||||||
|
tailwindcss = {
|
||||||
|
root_dir = function(fname)
|
||||||
|
local util = require "lspconfig.util"
|
||||||
|
return util.root_pattern("tailwind.config.js", "tailwind.config.ts", "postcss.config.js")(fname)
|
||||||
|
end,
|
||||||
|
settings = {
|
||||||
|
tailwindCSS = {
|
||||||
|
experimental = {
|
||||||
|
classRegex = {
|
||||||
|
{ "cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]" },
|
||||||
|
{ "cx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)" },
|
||||||
|
{ "cn\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
-- CSS LSP
|
||||||
|
cssls = {},
|
||||||
|
-- HTML LSP
|
||||||
|
html = {
|
||||||
|
filetypes = { "html", "typescriptreact", "javascriptreact" },
|
||||||
|
},
|
||||||
|
-- ESLint LSP
|
||||||
|
eslint = {
|
||||||
|
settings = {
|
||||||
|
workingDirectories = { mode = "auto" },
|
||||||
|
experimental = {
|
||||||
|
useFlatConfig = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Enhanced treesitter for TSX/React
|
||||||
|
{
|
||||||
|
"nvim-treesitter/nvim-treesitter",
|
||||||
|
optional = true,
|
||||||
|
opts = function(_, opts)
|
||||||
|
if opts.ensure_installed ~= "all" then
|
||||||
|
opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, {
|
||||||
|
"typescript",
|
||||||
|
"tsx",
|
||||||
|
"javascript",
|
||||||
|
"jsdoc",
|
||||||
|
"json",
|
||||||
|
"jsonc",
|
||||||
|
"css",
|
||||||
|
"scss",
|
||||||
|
"html",
|
||||||
|
"markdown",
|
||||||
|
"markdown_inline",
|
||||||
|
"regex",
|
||||||
|
"bash",
|
||||||
|
"vim",
|
||||||
|
"lua",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Treesitter context for React component awareness
|
||||||
|
{
|
||||||
|
"nvim-treesitter/nvim-treesitter-context",
|
||||||
|
event = { "BufReadPost", "BufNewFile" },
|
||||||
|
opts = {
|
||||||
|
enable = true,
|
||||||
|
max_lines = 3,
|
||||||
|
patterns = {
|
||||||
|
default = {
|
||||||
|
"class",
|
||||||
|
"function",
|
||||||
|
"method",
|
||||||
|
"for",
|
||||||
|
"while",
|
||||||
|
"if",
|
||||||
|
"switch",
|
||||||
|
"case",
|
||||||
|
"interface",
|
||||||
|
"struct",
|
||||||
|
"enum",
|
||||||
|
},
|
||||||
|
typescript = {
|
||||||
|
"class_declaration",
|
||||||
|
"abstract_class_declaration",
|
||||||
|
"function_declaration",
|
||||||
|
"method_definition",
|
||||||
|
"arrow_function",
|
||||||
|
"function_expression",
|
||||||
|
"lexical_declaration",
|
||||||
|
"variable_declaration",
|
||||||
|
},
|
||||||
|
typescriptreact = {
|
||||||
|
"class_declaration",
|
||||||
|
"function_declaration",
|
||||||
|
"method_definition",
|
||||||
|
"arrow_function",
|
||||||
|
"function_expression",
|
||||||
|
"jsx_element",
|
||||||
|
"jsx_self_closing_element",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- TypeScript utilities and tools
|
||||||
|
{
|
||||||
|
"pmizio/typescript-tools.nvim",
|
||||||
|
ft = { "typescript", "typescriptreact", "javascript", "javascriptreact" },
|
||||||
|
dependencies = { "nvim-lua/plenary.nvim", "neovim/nvim-lspconfig" },
|
||||||
|
opts = {
|
||||||
|
settings = {
|
||||||
|
separate_diagnostic_server = true,
|
||||||
|
publish_diagnostic_on = "insert_leave",
|
||||||
|
expose_as_code_action = "all",
|
||||||
|
tsserver_file_preferences = {
|
||||||
|
includeInlayParameterNameHints = "all",
|
||||||
|
includeInlayParameterNameHintsWhenArgumentMatchesName = true,
|
||||||
|
includeInlayFunctionParameterTypeHints = true,
|
||||||
|
includeInlayVariableTypeHints = true,
|
||||||
|
includeInlayVariableTypeHintsWhenTypeMatchesName = true,
|
||||||
|
includeInlayPropertyDeclarationTypeHints = true,
|
||||||
|
includeInlayFunctionLikeReturnTypeHints = true,
|
||||||
|
includeInlayEnumMemberValueHints = true,
|
||||||
|
},
|
||||||
|
tsserver_format_options = {
|
||||||
|
allowIncompleteCompletions = false,
|
||||||
|
allowRenameOfImportPath = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Mason LSP configurations
|
||||||
|
{
|
||||||
|
"williamboman/mason-lspconfig.nvim",
|
||||||
|
optional = true,
|
||||||
|
opts = function(_, opts)
|
||||||
|
opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, {
|
||||||
|
"tsserver",
|
||||||
|
"tailwindcss",
|
||||||
|
"cssls",
|
||||||
|
"html",
|
||||||
|
"eslint",
|
||||||
|
"jsonls",
|
||||||
|
})
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- React/JSX snippets and helpers
|
||||||
|
{
|
||||||
|
"dsznajder/vscode-es7-react-js-snippets",
|
||||||
|
build = "yarn install --frozen-lockfile && yarn compile",
|
||||||
|
ft = { "javascript", "typescript", "javascriptreact", "typescriptreact" },
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Auto-close and auto-rename JSX tags
|
||||||
|
{
|
||||||
|
"windwp/nvim-ts-autotag",
|
||||||
|
event = { "BufReadPost", "BufNewFile" },
|
||||||
|
ft = {
|
||||||
|
"html",
|
||||||
|
"javascript",
|
||||||
|
"typescript",
|
||||||
|
"javascriptreact",
|
||||||
|
"typescriptreact",
|
||||||
|
"xml",
|
||||||
|
"vue",
|
||||||
|
"svelte",
|
||||||
|
},
|
||||||
|
opts = {
|
||||||
|
autotag = {
|
||||||
|
enable = true,
|
||||||
|
enable_rename = true,
|
||||||
|
enable_close = true,
|
||||||
|
enable_close_on_slash = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Package info for package.json
|
||||||
|
{
|
||||||
|
"vuki656/package-info.nvim",
|
||||||
|
event = "BufRead package.json",
|
||||||
|
dependencies = { "MunifTanjim/nui.nvim" },
|
||||||
|
opts = {},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Crates.io integration (useful for Rust tooling in Workers)
|
||||||
|
{
|
||||||
|
"saecki/crates.nvim",
|
||||||
|
event = "BufRead Cargo.toml",
|
||||||
|
dependencies = { "nvim-lua/plenary.nvim" },
|
||||||
|
opts = {
|
||||||
|
lsp = {
|
||||||
|
enabled = true,
|
||||||
|
actions = true,
|
||||||
|
completion = true,
|
||||||
|
hover = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
Reference in new issue
Block a user