Skip to content

When completing HTML tags within a template tag in Neovim, text gets overwritten in unexpected areas. #5331

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
tadashi-aikawa opened this issue Apr 20, 2025 · 9 comments

Comments

@tadashi-aikawa
Copy link

Vue - Official extension or vue-tsc version

2.2.8

VSCode version

1.99.3

Vue version

3.5.13

TypeScript version

5.8.3

System Info

System:
    OS: Linux 5.15 Ubuntu 24.04.1 LTS 24.04.1 LTS (Noble Numbat)
    CPU: (20) x64 12th Gen Intel(R) Core(TM) i9-12900H
    Memory: 10.34 GB / 15.43 GB
    Container: Yes
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.8.0 - ~/.local/share/mise/installs/node/22.8.0/bin/node
    Yarn: 1.22.22 - ~/.local/share/mise/installs/node/22.8.0/bin/yarn
    npm: 10.8.2 - ~/.local/share/mise/installs/node/22.8.0/bin/npm
    bun: 1.2.9 - ~/.local/share/mise/installs/bun/1.2.9/bin/bun
  Browsers:
    Chrome: 132.0.6834.83

package.json dependencies

{
  "dependencies": {
    "vue": "^3.5.13"
  },
  "devDependencies": {
    "@tsconfig/node22": "^22.0.1",
    "@types/node": "^22.14.0",
    "@vitejs/plugin-vue": "^5.2.3",
    "@vue/tsconfig": "^0.7.0",
    "npm-run-all2": "^7.0.2",
    "typescript": "~5.8.0",
    "vite": "^6.2.4",
    "vite-plugin-vue-devtools": "^7.7.2",
    "vue-tsc": "^2.2.8"
  }
}

Steps to reproduce

Create a vue project.

bun create vue@latest vue-sandbox # select "TypeScript" only
cd vue-sandbox
bun i

Open and edit src/App.vue in Neovim.

<script setup lang="ts">
</script>

<template>
  <h1>title</h1>
</template>

When type <div and display suggestions.

<script setup lang="ts">
</script>

<template>
  <div
  <h1>title</h1>
</template>

Image

Then select/confirm one of the suggestions div.

What is expected?

<script setup lang="ts">
</script>

<template>
  <div
  <h1>title</h1>
</template>

What is actually happening?

<script setup lang="ts">
</script>

<template>
  <div1>title</h1>
</template>
2025-04-20_14h01_21.mp4

Link to minimal reproduction

No response

Any additional comments?

I didn't experience this issue when using the "Vue - Official" extension in VSCode, and the problem doesn't occur in Vue files that don't have a <script> tag.

While using Neovim with plugins like nvim-lspconfig and blink.cmp for LSP and completion support, I checked the LSP debug logs and found the following output from the Volar LSP:

[DEBUG][2025-04-20 13:17:41] ...m/lsp/client.lua:677	"LSP[volar]"	"client.request"	2	"completionItem/resolve"	{ documentation = { kind = "markdown", value = "The div element has no special meaning at all. It represents its children. It can be used with the class, lang, and title attributes to mark up semantics common to a group of consecutive elements.\n\n[MDN Reference](https://developer.mozilla.org/docs/Web/HTML/Element/div)" }, exact = false, insertTextFormat = 1, kind = 10, label = "div", score = 20, sortText = "\1div", textEdit = { newText = "div", range = { ["end"] = { character = 5, line = 7 }, start = { character = 3, line = 6 } } } }	<function 1>	12

Looking at this log, I can see that range.start and range.end are pointing to different lines. Since this issue doesn't occur with other LSPs, I suspect this might be specific to the Volar LSP implementation.

The code that generated this log output can be found in the Neovim repository here:
https://github.com/neovim/neovim/blob/4b909528516032b002a4a32f3e06f0eb6185ea6b/runtime/lua/vim/lsp/client.lua?plain=1#L678

This is my first time investigating LSP logs and troubleshooting this kind of issue, so please let me know if I've missed anything or if my comments aren't relevant :)

@KazariEX
Copy link
Member

@RayGuo-ergou

@RayGuo-ergou
Copy link
Contributor

can you share a minimal config to reproduce this issue? I cannot reproduce this on my end. Or try with only blinks and volar to see if this is still reproducible.

Image

the debug log i got

[DEBUG][2025-04-21 13:31:40] ...m/lsp/client.lua:680 "LSP[volar]" "client.request" 4 "completionItem/resolve" { documentation = { kind = "markdown", value = "The div element has no special meaning at all. It represents its children. It can be used with the class, lang, and title attributes to mark up semantics common to a group of consecutive elements.\n\nMDN Reference" }, exact = true, insertTextFormat = 1, kind = 10, label = "div", score = 36, sortText = "\1div", textEdit = { newText = "div", range = { ["end"] = { character = 3, line = 4 }, start = { character = 3, line = 4 } } } } <function 1> 2

btw here's what nvim-cmp looks like, the new line in my gif seems added by blinks as the range is on same line from the response.

Image

@tadashi-aikawa
Copy link
Author

tadashi-aikawa commented Apr 21, 2025

@RayGuo-ergou
Thank you for your reply! Regarding the minimal config to reproduce, I created the following repro.lua and ran nvim -u repro.lua src/App.vue, which reproduced the issue:

local root = vim.fn.fnamemodify("./.repro", ":p")
for _, name in ipairs({ "config", "data", "state", "cache" }) do
	vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end

local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
	vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath })
end
vim.opt.runtimepath:prepend(lazypath)

local plugins = {
	{
		"saghen/blink.cmp",
		version = "*",
		opts = {
			keymap = {
				preset = "enter",
			},
			completion = {
				documentation = { auto_show = true, window = { border = "rounded" } },
			},
		},
	},
	{
		"neovim/nvim-lspconfig",
		lazy = false,
		dependencies = { "saghen/blink.cmp" },
		config = function()
			local capabilities = {
				textDocument = {
					foldingRange = {
						dynamicRegistration = false,
						lineFoldingOnly = true,
					},
				},
			}
			capabilities = require("blink.cmp").get_lsp_capabilities(capabilities)

			local lspconfig = require("lspconfig")

			lspconfig.volar.setup({
				capabilities = capabilities,
			})
		end,
	},
}
require("lazy").setup(plugins, {
	root = root .. "/plugins",
})
2025-04-21_22h00_14.mp4

However, this configuration depends on nvim-lspconfig, so it's not truly minimal. I'll try to verify the behavior without nvim-lspconfig 👍

$ nvim --version
NVIM v0.11.0
Build type: Release
LuaJIT 2.1.1741730670
Run "nvim -V1 -v" for more info

Plugin versions:

  • blink.cmp: cb5e346
  • nvim-lspconfig: 32b6a64

@tadashi-aikawa
Copy link
Author

@RayGuo-ergou
I was able to reproduce this with the repro.lua below. This is the minimal config I could confirm when using blink.cmp.

local root = vim.fn.fnamemodify("./.repro", ":p")
for _, name in ipairs({ "config", "data", "state", "cache" }) do
	vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end

local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
	vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath })
end
vim.opt.runtimepath:prepend(lazypath)

local function get_typescript_server_path(root_dir)
	local project_root = vim.fs.dirname(vim.fs.find("node_modules", { path = root_dir, upward = true })[1])
	return project_root and vim.fs.joinpath(project_root, "node_modules", "typescript", "lib") or ""
end

---@type vim.lsp.Config
vim.lsp.config.volar = {
	cmd = { "vue-language-server", "--stdio" },
	filetypes = { "vue" },
	root_markers = { "package.json" },
	init_options = { typescript = { tsdk = "" } },
	before_init = function(_, config)
		if config.init_options and config.init_options.typescript and config.init_options.typescript.tsdk == "" then
			config.init_options.typescript.tsdk = get_typescript_server_path(config.root_dir)
		end
	end,
}
vim.lsp.enable({ "volar" })

local plugins = {
	{
		"saghen/blink.cmp",
		version = "*",
		opts = {},
	},
}
require("lazy").setup(plugins, {
	root = root .. "/plugins",
})
nvim -u repro.lua src/App.vue

@RayGuo-ergou
Copy link
Contributor

RayGuo-ergou commented Apr 21, 2025

Hi @tadashi-aikawa Thanks for providing the reproduction config but unfortunately I still cannot reproduce it.(just figured that c-y is default accept for blink, so it does not emit a new line)

just to be clear I was using ['<C-y>'] = { 'select_and_accept' }, to accept it.

Image

nvim -v
Found existing alias for "nvim". You should use: "vim"
NVIM v0.12.0-dev-178+gd3cded796c
Build type: RelWithDebInfo
LuaJIT 2.1.1744317938
Run "nvim -V1 -v" for more info

This is my neovim version

@RayGuo-ergou
Copy link
Contributor

Also tried on both 2.2.8 and 3.0.0 alpha 4 both work as excepted.

@tadashi-aikawa
Copy link
Author

@RayGuo-ergou
Thank you for your quick confirmation. I tried matching my Neovim version with yours, but the issue still persists (I can still reproduce it).

NVIM v0.12.0-dev-178+gd3cded796c
Build type: RelWithDebInfo
LuaJIT 2.1.1744317938
Run "nvim -V1 -v" for more info

I've also confirmed that my Volar version is indeed 2.2.8.

$ vue-language-server --version
2.2.8

Additionally, in my environment, completions don't seem to appear even when I start typing right after e> in <template>. Perhaps something is causing the cursor position in Neovim to not be correctly passed to Volar.

I'll keep an eye on it for now. Thank you for your valuable time!

2025-04-21_23h58_28.mp4

@tadashi-aikawa
Copy link
Author

Hi, @RayGuo-ergou :)

I'd like to report that the issue has been resolved. In conclusion, reinstalling Volar fixed the problem.

Details

Today, I checked on my work machine and couldn't reproduce the issue. I verified this with both versions 2.2.8 and 2.2.10.

When I returned home and checked with the same versions, the issue still occurred on my home machine. After uninstalling and reinstalling @vue/language-server, the problem was resolved.

I have no idea why this issue was occurring so specifically on my setup, but thanks to your help, I can now comfortably develop in Vue! Thank you very much for your considerate support!

@RayGuo-ergou
Copy link
Contributor

@tadashi-aikawa Glad that you have resolved. Happy coding.🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants