Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions lua/markview/renderers/markdown_inline.lua
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,11 @@ inline.link_hyperlink = function (buffer, item)
hl_group = utils.set_hl(config.hl)
});

--- NOTE: hl_mode must NOT be "combine" here. This extmark conceals
--- the URL portion `](https://…)` which can span hundreds of bytes.
--- With "combine" the virt_text highlight (e.g. underline) bleeds
--- across every concealed byte, producing ghost underlines on the
--- phantom screen rows created by soft-wrap of the hidden text.
vim.api.nvim_buf_set_extmark(buffer, inline.ns, r_label[3], r_label[4], {
undo_restore = false, invalidate = true,
end_row = range.row_end,
Expand All @@ -626,8 +631,6 @@ inline.link_hyperlink = function (buffer, item)
{ config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) },
{ config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) }
},

hl_mode = "combine"
});

if r_label[1] == r_label[3] then
Expand Down Expand Up @@ -734,6 +737,8 @@ inline.link_image = function (buffer, item)
hl_group = utils.set_hl(config.hl)
});

--- NOTE: hl_mode must NOT be "combine" here — same reason as link_hyperlink.
--- See the comment there for full explanation.
vim.api.nvim_buf_set_extmark(buffer, inline.ns, r_label[3], r_label[4], {
undo_restore = false, invalidate = true,
end_row = range.row_end,
Expand All @@ -745,8 +750,6 @@ inline.link_image = function (buffer, item)
{ config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) },
{ config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) }
},

hl_mode = "combine"
});

if r_label[1] == r_label[3] then
Expand Down
29 changes: 29 additions & 0 deletions test/inline_conceal_wrap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
; Concealed link/image URLs and soft-wrap — ghost underlines
The concealing extmark for a link/image hides the `](https://…)` portion, which
can span hundreds of bytes. When that hidden text is long enough to soft-wrap,
Neovim creates phantom screen rows for it. With `hl_mode = "combine"` on the
conceal extmark, the virtual-text highlight (e.g. the link underline) bleeds
across every concealed byte and paints those phantom rows, producing "ghost"
underlines/highlights on otherwise-empty wrapped rows.
To reproduce, open this file with `:setlocal wrap` in a NARROW window (e.g.
40–60 columns) so the long URLs would wrap if they weren't concealed. With the
fix, no stray underline/highlight should appear below the visible link labels;
the concealed URL must not leave a colored trail on wrapped rows.
### Long hyperlink URLs (primary repro)
- [Neovim API reference](https://neovim.io/doc/user/api.html#nvim_buf_set_extmark()-nvim_buf_del_extmark()-nvim_buf_get_extmarks()-and-related-extmark-functions)
- [CommonMark emphasis rules](https://spec.commonmark.org/0.31.2/#emphasis-and-strong-emphasis-combined-with-links-and-images)
- [short link for control](https://example.com)
### Long image URLs
- ![treesitter playground screenshot](https://raw.githubusercontent.com/nvim-treesitter/playground/master/assets/screenshot-with-custom-queries-and-hl-groups.png)
- ![short image control](https://example.com/icon.svg)
### Links inside table cells (conceal + wrap in narrow columns)
| Kind | With long URL |
|-------------|--------------------------------------------------------------------------------------------------------|
| Hyperlink | [Neovim API reference](https://neovim.io/doc/user/api.html#nvim_buf_set_extmark()-full-details) |
| Image | ![screenshot](https://raw.githubusercontent.com/nvim-treesitter/playground/master/assets/screenshot.png) |
| Bold + link | **[bold link with long URL](https://spec.commonmark.org/0.31.2/#emphasis-and-strong-emphasis)** |
| Short (ctl) | [ref](https://a.co) |
### Multiple concealed links on one wrapping line
This paragraph has [first link](https://neovim.io/doc/user/api.html#first-very-long-anchor-for-wrapping) and [second link](https://neovim.io/doc/user/lua.html#second-very-long-anchor-for-wrapping) and [third link](https://neovim.io/doc/user/options.html#third-very-long-anchor) all on one line so their concealed URLs force soft-wrap.

<!-- vim: set wrap linebreak: -->
Loading