Skip to content
Merged
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
19 changes: 15 additions & 4 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ Neovim 用の Markdown レンダリングエンジンです。生の Markdown

- **リッチなインライン書式** — 太字、取り消し線、インラインコード、リンク、Obsidian `==highlight==` をその場でレンダリング
- **テーブル** — 罫線文字による描画、列アラインメント、比例サイズ調整、セル内インライン書式
- **コールアウト & 折りたたみ** — GitHub / Obsidian のアラートタイプに対応。色付きボーダー・アイコン・クリックで折りたたみ切り替え
- **コードブロック** — treesitter シンタックスハイライト付きフェンスコードブロック。省略時はクリックで展開
- **コールアウト & 折りたたみ** — GitHub / Obsidian のアラートタイプに対応。色付きボーダー・アイコン・クリックまたは `za` / `<CR>` で折りたたみ切り替え
- **コードブロック** — treesitter シンタックスハイライト付きフェンスコードブロック。省略時はクリックまたは `za` / `<CR>` で展開
- **画像** — ローカルおよび Web 画像(PNG, JPEG, WebP, GIF, アニメーション GIF)をターミナルグラフィクスプロトコルでインライン表示
- **動画** — ローカルおよび Web 動画(MP4, WebM, MOV, AVI, MKV, M4V)をアニメーションフレームとしてインライン再生
- **Mermaid ダイアグラム** — 画像としてインライン表示
- **CJK 対応ワードラップ** — JIS X 4051 禁則処理 + [BudouX](https://github.com/google/budoux)([budoux.lua](https://github.com/delphinus/budoux.lua) 経由)によるオプションのフレーズ分割
- **クリック可能リンク** — マウスクリックで URL を開く。対応ターミナルでは OSC 8 ハイパーリンク
- **`<details>` 対応** — クリックで折りたたみ可能なセクション。`open` 属性にも対応
- **`<details>` 対応** — クリックまたは `za` / `<CR>` で折りたたみ可能なセクション。`open` 属性にも対応
- **ライブラリ API** — レンダリングエンジンを自作プラグインからプログラム的に利用可能

<figure align="center">
Expand Down Expand Up @@ -144,6 +144,17 @@ vim.keymap.set("n", "<leader>md", "<Plug>(md-render-demo)", { desc = "Mar
| `<Plug>(md-render-split)` | ウィンドウを分割してソースとレンダリング表示を並べる |
| `<Plug>(md-render-demo)` | 対応する全 Markdown 記法のデモウィンドウを表示 |

### プレビュー内のキー

レンダリングされたプレビュー(フローティング・タブ・その場トグル)内では、以下のバッファローカルなキーが自動で設定されます:

| キー | 動作 |
|---|---|
| `za` | カーソル行の折りたたみ / 展開ブロックを切り替える(該当しない行では何もしない) |
| `<CR>` | カーソル行の折りたたみ / 展開ブロックを切り替える。該当しなければウィンドウを閉じる(フローティング / タブモードのみ) |
| `<LeftMouse>` | クリックで折りたたみ・展開を切り替え、リンクを開く |
| `q` / `<Esc>` | ウィンドウを閉じる(フローティング / タブモードのみ) |

## コマンド

このプラグインが公開するユーザコマンドは `:MdRender` ひとつで、サブコマンドで動作モードを切り替えます。
Expand Down Expand Up @@ -178,7 +189,7 @@ vim.keymap.set("n", "<leader>md", "<Plug>(md-render-demo)", { desc = "Mar
- 同じソースが複数のウィンドウで表示されている場合、切替はそのウィンドウだけに作用し、他のウィンドウの編集は次に当該ウィンドウをレンダーモードにした時点で反映されます。
- カーソル位置は source line マップを介してソース ↔ レンダー間を往復します。
- レンダーモードのウィンドウでは `number` / `relativenumber` / `list` が無効化されます。元の値はウィンドウに保存され、ソースに戻したときに復元されます。
- レンダーモード中、`q` / `<Esc>` / `<CR>` は閉じる動作に**割り当てられません**。ソースに戻すには再度 `:MdRender toggle` を呼びます。`<LeftMouse>` は折りたたみ・展開・リンク open を引き続き処理します
- レンダーモード中、`q` / `<Esc>` / `<CR>` は閉じる動作に**割り当てられません**。ソースに戻すには再度 `:MdRender toggle` を呼びます。`<LeftMouse>` / `za` / `<CR>` は折りたたみ・展開を引き続き切り替えます(リンク open は `<LeftMouse>`)

### Insert モード連動の自動トグル(実験的)

Expand Down
19 changes: 15 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ A Markdown rendering engine for Neovim. Transforms raw Markdown into richly high

- **Rich inline formatting** — bold, strikethrough, inline code, links, Obsidian `==highlight==`, all rendered in-place
- **Tables** — box-drawing borders, column alignment, proportional sizing, and inline formatting within cells
- **Callouts & folds** — GitHub and Obsidian alert types with colored borders, icons, and click-to-toggle folding
- **Code blocks** — fenced blocks with treesitter syntax highlighting; expandable when truncated
- **Callouts & folds** — GitHub and Obsidian alert types with colored borders, icons, and folding you can toggle by clicking or with `za` / `<CR>`
- **Code blocks** — fenced blocks with treesitter syntax highlighting; expandable when truncated (click or `za` / `<CR>`)
- **Images** — local and web images (PNG, JPEG, WebP, GIF, animated GIF) displayed inline via terminal graphics protocol
- **Video** — local and web video (MP4, WebM, MOV, AVI, MKV, M4V) played as animated frames inline
- **Mermaid diagrams** — rendered as images inline
- **CJK-aware word wrapping** — JIS X 4051 kinsoku shori + optional [BudouX](https://github.com/google/budoux) phrase segmentation via [budoux.lua](https://github.com/delphinus/budoux.lua)
- **Clickable links** — mouse click to open URLs; hover the mouse over a link to peek the full URL in a subtle floating window; OSC 8 hyperlink support for compatible terminals
- **`<details>` support** — collapsible sections with click-to-toggle, respecting the `open` attribute
- **`<details>` support** — collapsible sections you can toggle by clicking or with `za` / `<CR>`, respecting the `open` attribute
- **Library API** — use the rendering engine programmatically from your own plugins

<figure align="center">
Expand Down Expand Up @@ -144,6 +144,17 @@ vim.keymap.set("n", "<leader>md", "<Plug>(md-render-demo)", { desc = "Mar
| `<Plug>(md-render-split)` | Open a split showing source and rendered Markdown |
| `<Plug>(md-render-demo)` | Show a demo window with all supported Markdown notations |

### In-preview keys

Inside a rendered preview (floating, tab, or in-place toggle), these buffer-local keys are set automatically:

| Key | Action |
|---|---|
| `za` | Toggle the fold / expandable region under the cursor (no-op elsewhere) |
| `<CR>` | Toggle the fold / expandable region under the cursor; otherwise close the window (in floating / tab mode) |
| `<LeftMouse>` | Toggle folds, expand regions, and open links by clicking |
| `q` / `<Esc>` | Close the window (floating / tab mode only) |

## Commands

The plugin exposes a single `:MdRender` command with subcommands:
Expand Down Expand Up @@ -178,7 +189,7 @@ Behavior:
- When the same source is shown in multiple windows, only the invoking window swaps; edits from other windows are reflected on the next toggle into render mode.
- Cursor position round-trips between source and render via the source-line mapping.
- `number`, `relativenumber`, and `list` are turned off on render-mode windows. The originals are stashed on the window and restored when toggling back to source.
- Inside render mode, `q` / `<Esc>` / `<CR>` are **not** bound to close — call `:MdRender toggle` again to return to source mode. `<LeftMouse>` still toggles folds, expands regions, and opens links.
- Inside render mode, `q` / `<Esc>` / `<CR>` are **not** bound to close — call `:MdRender toggle` again to return to source mode. `<LeftMouse>`, `za`, and `<CR>` still toggle folds and expand regions (and `<LeftMouse>` opens links).

### Auto-toggle on Insert mode (experimental)

Expand Down
22 changes: 13 additions & 9 deletions doc/md-render.jax
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ md-render.nvim は Neovim 用の Markdown レンダリングエンジンです
`==highlight==` )
- テーブル(罫線文字による描画、列アラインメント、比例サイズ調整)
- コールアウト & 折りたたみ(GitHub / Obsidian のアラートタイプに対応。色付き
ボーダー・アイコン・クリック折りたたみ切り替え
- コードブロック(treesitter シンタックスハイライト付き。省略時はクリックで展
ボーダー・アイコン・クリックまたは `za` / `<CR>` で折りたたみ切り替え
- コードブロック(treesitter シンタックスハイライト付き。省略時はクリックまた
は `za` / `<CR>` で展開
- 画像(PNG, JPEG, WebP, GIF, アニメーション GIF)をターミナルグラフィクスプロ
トコルでインライン表示
- 動画(MP4, WebM, MOV, AVI, MKV, M4V)をアニメーションフレームとしてインラ
Expand All @@ -51,7 +51,7 @@ md-render.nvim は Neovim 用の Markdown レンダリングエンジンです
割)
- クリック可能リンク(マウスクリックで URL を開く。マウスをリンクに乗せると
完全な URL を控え目なフロートウィンドウに表示。OSC 8 ハイパーリンク対応)
- `<details>` 対応(クリックで折りたたみ可能なセクション
- `<details>` 対応(クリックまたは `za` / `<CR>` で折りたたみ可能なセクション
- ライブラリ API(自作プラグインからプログラム的に利用可能)

==============================================================================
Expand Down Expand Up @@ -139,7 +139,10 @@ lazy.nvim の場合: >lua
プレビューウィンドウ内では以下のキーが使えます:

`q` / `<Esc>` プレビューウィンドウを閉じる
`<CR>` コールアウトの折りたたみ / 省略領域の展開
`za` カーソル行のコールアウトの折りたたみ / 省略領域の
展開を切り替える (該当しない行では何もしない)
`<CR>` カーソル行のコールアウトの折りたたみ / 省略領域の
展開を切り替える。該当しなければウィンドウを閉じる
`<LeftMouse>` リンクのクリック、折りたたみ、領域展開
`<MouseMove>` マウスをリンクに乗せると、エディタ下部の小さな
フロートウィンドウに完全な URL を表示。
Expand All @@ -148,8 +151,9 @@ lazy.nvim の場合: >lua

|:MdRender-toggle| で開かれたレンダーモードのバッファでは `q` / `<Esc>` /
`<CR>` は閉じる動作に**割り当てられません**。ソースに戻すには再度
|:MdRender-toggle| を呼びます。`<LeftMouse>` は折りたたみ・展開・リンクを
引き続き処理し、`<MouseMove>` の URL 表示も有効なままです。
|:MdRender-toggle| を呼びます。`<LeftMouse>` / `za` / `<CR>` は折りたたみ・
展開を引き続き切り替え (リンク open は `<LeftMouse>`)、`<MouseMove>` の URL
表示も有効なままです。

==============================================================================
コマンド *md-render-commands*
Expand Down Expand Up @@ -253,8 +257,8 @@ lazy.nvim の場合: >lua
レンダーバッファ上で効くもの: ~

読み取り系操作: 移動 (hjkl, gg, G, ...)、検索 (/, ?)、yank (y)、
ビジュアル選択、マーク、<LeftMouse>(折りたたみ・展開・リンク
open)。
ビジュアル選択、マーク、`za` / `<CR>`(折りたたみ・展開の切り替え)、
<LeftMouse>(折りたたみ・展開・リンク open)。

`:w` / `:w!` は source バッファへ転送されるため、render モード
を抜けずに保存できます。`:w other.md` や `:saveas` のような別名
Expand Down
19 changes: 12 additions & 7 deletions doc/md-render.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ Features: ~
Obsidian`==highlight==`)
- Tables with box-drawing borders, column alignment, and proportional sizing
- Callouts and folds (GitHub / Obsidian alert types with colored borders,
icons, and click-to-toggle folding)
icons, and folding you can toggle by click or `za` / `<CR>`)
- Code blocks with treesitter syntax highlighting; expandable when truncated
(click or `za` / `<CR>`)
- Images (PNG, JPEG, WebP, GIF, animated GIF) displayed inline via terminal
graphics protocol
- Video (MP4, WebM, MOV, AVI, MKV, M4V) played as animated frames inline
Expand All @@ -48,7 +49,7 @@ Features: ~
segmentation)
- Clickable links (mouse click to open URLs; mouse hover peeks the full URL
in a subtle floating window; OSC 8 hyperlink support)
- `<details>` support (collapsible sections with click-to-toggle)
- `<details>` support (collapsible sections; toggle by click or `za` / `<CR>`)
- Library API for programmatic use from other plugins

==============================================================================
Expand Down Expand Up @@ -138,7 +139,10 @@ Map them yourself: >lua
Inside the preview window, the following keys are available:

`q` / `<Esc>` Close the preview window
`<CR>` Toggle callout fold / expand truncated region
`za` Toggle the callout fold / expandable region under the
cursor (no-op when the cursor is not on one)
`<CR>` Toggle the callout fold / expandable region under the
cursor; otherwise close the preview window
`<LeftMouse>` Click links, toggle folds, expand regions
`<MouseMove>` Hover a link to peek its full URL in a small floating
window at the bottom of the editor. Requires
Expand All @@ -147,8 +151,9 @@ Inside the preview window, the following keys are available:

Inside a render-mode buffer opened with |:MdRender-toggle|, `q` / `<Esc>` /
`<CR>` are NOT bound to close — call |:MdRender-toggle| again to return to
source mode. `<LeftMouse>` still toggles folds, expands regions, and
opens links; `<MouseMove>` hover-peek also stays active.
source mode. `<LeftMouse>`, `za`, and `<CR>` still toggle folds and expand
regions (and `<LeftMouse>` opens links); `<MouseMove>` hover-peek also stays
active.

==============================================================================
COMMANDS *md-render-commands*
Expand Down Expand Up @@ -250,8 +255,8 @@ still registered as deprecated aliases — see |md-render-deprecated-commands|.
What works on the render buffer: ~

Read-only operations: motion (hjkl, gg, G, ...), search (/, ?),
yank (y), visual selection, marks, and <LeftMouse> (folds,
expand, link open).
yank (y), visual selection, marks, `za` / `<CR>` (toggle folds
and expand regions), and <LeftMouse> (folds, expand, link open).

`:w` and `:w!` are forwarded to the source buffer so you can
save without leaving render mode. Different filenames (e.g.
Expand Down
86 changes: 69 additions & 17 deletions lua/md-render/display_utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -317,12 +317,70 @@ function M.setup_float_keymaps(buf, ns, win, content, close_handle, opts)
end

local close_keys = opts.close_keys or { "q", "<Esc>", "<CR>" }
local cr_is_close = vim.tbl_contains(close_keys, "<CR>")
for _, key in ipairs(close_keys) do
vim.api.nvim_buf_set_keymap(buf, "n", key, ":close<CR>", { noremap = true, silent = true })
-- <CR> is bound below so it can toggle a block under the cursor first and
-- fall back to closing only when the cursor is not on a foldable region.
if key ~= "<CR>" then
vim.api.nvim_buf_set_keymap(buf, "n", key, ":close<CR>", { noremap = true, silent = true })
end
end

UrlHover.attach(buf, ns, win)

-- Return the foldable callout header at the given 0-indexed rendered line, or nil.
---@param line integer
---@return MdRender.CalloutFold?
local function fold_at(line)
local cur_content = get_content()
if on_fold_toggle and cur_content.callout_folds then
for _, fold in ipairs(cur_content.callout_folds) do
if fold.header_line == line then return fold end
end
end
end

-- Return the expandable region containing the given 0-indexed rendered line, or nil.
---@param line integer
---@return MdRender.ExpandableRegion?
local function region_at(line)
local cur_content = get_content()
if on_expand_toggle and cur_content.expandable_regions then
for _, region in ipairs(cur_content.expandable_regions) do
if line >= region.start_line and line <= region.end_line then return region end
end
end
end

-- Toggle the foldable callout or expandable region under the cursor.
-- Returns true if something was toggled.
---@return boolean
local function toggle_at_cursor()
local line = vim.api.nvim_win_get_cursor(0)[1] - 1
local fold = fold_at(line)
if fold then
on_fold_toggle(fold.source_line, not fold.collapsed)
return true
end
local region = region_at(line)
if region then
on_expand_toggle(region.block_id, not region.expanded)
return true
end
return false
end

-- `za` toggles the block under the cursor (no-op when not on one). Overriding
-- it buffer-locally also suppresses Vim's default "E490: No fold found".
vim.keymap.set("n", "za", toggle_at_cursor, { buffer = buf, noremap = true, silent = true })

-- `<CR>` toggles the block under the cursor; otherwise it closes the window
-- when it is a close key (float/tab mode), and is a no-op in toggle mode.
vim.keymap.set("n", "<CR>", function()
if toggle_at_cursor() then return end
if cr_is_close then vim.cmd.close() end
end, { buffer = buf, noremap = true, silent = true })

vim.keymap.set("n", "<LeftRelease>", function()
local mouse = vim.fn.getmousepos()
if mouse.winid == win then
Expand Down Expand Up @@ -383,25 +441,19 @@ function M.setup_float_keymaps(buf, ns, win, content, close_handle, opts)
end

-- Check for foldable callout header click
if on_fold_toggle and cur_content.callout_folds then
for _, fold in ipairs(cur_content.callout_folds) do
if fold.header_line == click_line then
on_fold_toggle(fold.source_line, not fold.collapsed)
return
end
end
local fold = fold_at(click_line)
if fold then
on_fold_toggle(fold.source_line, not fold.collapsed)
return
end

-- Check for expandable region click (code blocks / tables)
if on_expand_toggle and cur_content.expandable_regions then
for _, region in ipairs(cur_content.expandable_regions) do
if click_line >= region.start_line and click_line <= region.end_line then
-- If click is on a URL, open it instead of toggling expansion
if try_open_url() then return end
on_expand_toggle(region.block_id, not region.expanded)
return
end
end
local region = region_at(click_line)
if region then
-- If click is on a URL, open it instead of toggling expansion
if try_open_url() then return end
on_expand_toggle(region.block_id, not region.expanded)
return
end

-- In OSC 8 terminals, the terminal handles link clicks natively.
Expand Down
Loading
Loading