Hover a
```mermaidblock in Markdown and see it rendered as ASCII art, right in a floating window — no browser, no image, just text.
Press K inside a mermaid fence:
┌──────┐ ┌───────┐ ┌────────┐ ┌───────┐
│ Edit ├────►│ Hover ├────►│ Render ├────►│ Float │
└──────┘ └───────┘ └────────┘ └───────┘
It works for sequence diagrams too:
┌────────┐ ┌──────────┐ ┌───────┐
│ Editor │ │ Renderer │ │ Float │
└────┬───┘ └─────┬────┘ └───┬───┘
│ source │ │
├──────────────►│ │
│ ascii │ │
│◄┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤ │
│ show │ │
├─────────────────────────────►│
- Hover to render — cursor in a
```mermaidblock, pressK, get an ASCII float. - Peek, then dive —
Kpeeks (closes on cursor move); pressKagain (KK) to enter a focusable, scrollable window for big diagrams.q/<Esc>to close. - Plays nice with LSP — keeps
Kbound even when your LSP maps it, and falls back tovim.lsp.buf.hoverwhen you're not in a mermaid block. - Readable by default — forces an opaque background and disables wrap, so diagrams never bleed through or fold over themselves.
- Zero runtime deps — pure Lua + the
mermaid-asciibinary. No Node, no headless browser.
-
Neovim ≥ 0.10 (uses
vim.system) -
mermaid-asciion yourPATH:go install github.com/AlexanderGrooff/mermaid-ascii@latest # make sure $(go env GOPATH)/bin is on your PATHSupports flowchart and sequence diagrams.
{
"Esequiel378/mermaid-hover.nvim",
ft = "markdown",
config = function()
require("mermaid-hover").setup()
end,
}use({
"Esequiel378/mermaid-hover.nvim",
config = function()
require("mermaid-hover").setup()
end,
})| Key / command | Where | Action |
|---|---|---|
K |
inside a ```mermaid block |
Peek: render into a floating window |
K again (KK) |
while the peek is open | Enter the float — focusable & scrollable |
q / <Esc> |
inside the focused float | Close it |
K |
outside a mermaid block | Falls through to vim.lsp.buf.hover |
:MermaidHover |
anywhere | Same as pressing K |
The peek closes itself the moment you move the cursor — KK quickly to keep it open
and scroll.
setup() takes an optional table. Defaults:
require("mermaid-hover").setup({
cmd = "mermaid-ascii", -- rendering binary (must be on PATH)
args = {}, -- extra CLI flags, e.g. { "--ascii" } or { "-x", "3" }
keymap = "K", -- buffer-local trigger; "" to disable
filetypes = { "markdown" }, -- where the keymap is attached
border = "rounded", -- float border (see :h nvim_open_win)
winblend = 0, -- float transparency; 0 = opaque
max_width = 120, -- clamp the float width
max_height = 40, -- clamp the float height
lsp_fallback = true, -- outside a block, K → vim.lsp.buf.hover
})mermaid-ascii spaces nodes generously (paddingX/paddingY default to 5), so big
flowchart TD graphs render tall and sparse. Pass tighter spacing through args:
require("mermaid-hover").setup({ args = { "-x", "3", "-y", "2" } })Use { "--ascii" } if you prefer plain +--+ ASCII over Unicode box-drawing.
┌─────────┐ cursor row ┌────────┐ source ┌────────┐ ascii ┌────────┐
│ buffer ├──────────────►│ detect ├──────────►│ render ├─────────►│ window │
└─────────┘ find_block └────────┘ stdin → └────────┘ float └────────┘
mermaid-ascii
The plugin is a few small, independently tested modules:
| Module | Responsibility |
|---|---|
mermaid-hover.detect |
pure: find the ```mermaid block containing a cursor row |
mermaid-hover.render |
wrap vim.system to pipe source through mermaid-ascii |
mermaid-hover.window |
open / focus / close the floating window |
mermaid-hover.config |
default options |
mermaid-hover.init |
setup() / hover() orchestration, keymap, user command |
could not run 'mermaid-ascii' … is it installed?
Install the binary (see Requirements) and confirm $(go env GOPATH)/bin
is on the PATH that Neovim sees (:echo $PATH).
A diagram shows red error text in the float.
That's mermaid-ascii's parser output. It supports flowchart and sequence diagrams only;
some syntax (hyphenated participant names, certain node decorations) isn't supported.
K does LSP hover instead of rendering.
You're not inside a ```mermaid block, or the cursor moved before you pressed it.
The plugin re-binds K on LspAttach, so it should win over an LSP mapping — if it
doesn't, check that markdown is in filetypes.
The float looks transparent / text bleeds through.
The plugin forces winblend = 0. If you still see it, something is overriding the float's
highlight; try a different border or report an issue.
make test # runs the plenary busted suite headlessTests require plenary.nvim (already present in
most setups). The suite covers block detection, the subprocess wrapper (with an injected
fake — no binary needed), the float, the LSP-keymap interaction, and a real end-to-end
render that is skipped when mermaid-ascii isn't installed.
MIT © Esequiel Albornoz
