Neovim マークダウンプレビュー - markdown-preview.nvim を選んだ理由

Neovim マークダウンプレビュー - markdown-preview.nvim を選んだ理由

作成日:
更新日:

Neovimでマークダウンをプレビューするプラグインを導入しました。

Redditでの議論も参考にしながら検討しました。

検討したプラグイン

Neovimのマークダウンプレビューは大きく3つのアプローチに分かれます。

アプローチ説明代表的なプラグイン
バッファ内レンダリングNeovimの画面上で装飾表示markview.nvim、render-markdown.nvim
ブラウザプレビュー外部ブラウザでHTML表示markdown-preview.nvim、peek.nvim
ターミナルプレビューターミナル内でレンダリングglow.nvim

それぞれ見ていきます。

1. markview.nvim(バッファ内レンダリング)

Neovimのバッファ内でマークダウンをレンダリングするプラグイン。 見出しやリスト、コードブロックが装飾されて表示されます。

特徴:

  • バッファ内でリアルタイムレンダリング
  • 追加のブラウザやツールが不要
  • Neovimの画面だけで完結
  • ハイブリッドモード(ノーマルモードで装飾、インサートモードで生テキスト)

2. render-markdown.nvim(バッファ内レンダリング)

markview.nvimと同じバッファ内レンダリング系。GitHub Stars 4,000超の人気プラグインです。

特徴:

  • モーダルレンダリング — ノーマルモードでは装飾表示、インサートモードでは生テキスト表示に自動切替
  • Anti-conceal — カーソル行の仮想テキストを非表示にして編集しやすくする
  • ファイルタイプ非依存 — Markdownが注入された任意のファイルタイプで動作
  • 大規模ファイル対応 — 表示範囲のみレンダリング、ファイルサイズで無効化可能
  • 見出し、コードブロック、テーブル、チェックボックス、リンク、LaTeXブロック、コールアウトなど幅広い要素に対応
lazy.nvimでのセットアップ
{
  'MeanderingProgrammer/render-markdown.nvim',
  dependencies = { 'nvim-treesitter/nvim-treesitter' },
  ft = { 'markdown' },
  opts = {
    render_modes = { 'n', 'c', 't' },
  },
}

markview.nvimとの違いは、render-markdown.nvimの方がより「編集の邪魔をしない」設計思想が強い点です。Anti-conceal機能やモーダルレンダリングで、編集中のストレスを軽減してくれます。

3. markdown-preview.nvim(ブラウザプレビュー)

ブラウザでマークダウンをプレビューするプラグイン。 Node.jsベースのローカルサーバーを立ち上げて、ブラウザでリアルタイムに確認できます。

特徴:

  • ブラウザでプレビュー(同期スクロール対応)
  • リアルタイム同期(WebSocket)
  • Mermaid、KaTeX、PlantUML、Chart.js、Flowchart、シーケンス図、dot(Graphviz)に対応
  • カスタムCSS / ハイライトCSS でスタイル変更可能
  • リモートプレビュー対応(mkdp_open_to_the_world

4. peek.nvim(ブラウザプレビュー)

markdown-preview.nvimと同じブラウザプレビュー系ですが、Denoランタイムで動作します。

特徴:

  • Deno ベース(Node.js不要、Denoが必要)
  • GitHub風のスタイルでレンダリング
  • KaTeX(数式)、Mermaid(図)に対応
  • webview / ブラウザ / カスタムアプリから表示方法を選択可能
  • プレビューウィンドウ内でvimキー操作(j/k スクロール、u/d 半ページ、g/G 先頭/末尾)
lazy.nvimでのセットアップ
{
  'toppair/peek.nvim',
  event = { 'VeryLazy' },
  build = 'deno task --quiet build:fast',
  config = function()
    require('peek').setup({
      theme = 'dark',
      app = 'browser',
    })
    vim.api.nvim_create_user_command('PeekOpen', require('peek').open, {})
    vim.api.nvim_create_user_command('PeekClose', require('peek').close, {})
  end,
}

markdown-preview.nvimとの違いは、peek.nvimの方が軽量で設定がシンプルな反面、対応する記法(PlantUML、Chart.js、Flowchart、dot等)は少なめです。

5. glow.nvim(ターミナルプレビュー) ※アーカイブ済み

Charm社の glow をNeovim内で使うプラグイン。ターミナル上でマークダウンをレンダリングします。

特徴:

  • ターミナル内で完結(ブラウザ不要)
  • glow CLIのレンダリング品質
  • シンタックスハイライト付き

ただし、2025年3月にリポジトリがアーカイブされており、今後のメンテナンスは期待できません。glow CLI自体は健在なので、プラグインなしで :!glow % のようにコマンドとして使う方法はあります。

選んだのは markdown-preview.nvim

いくつか試した結果、markdown-preview.nvim を選びました。

選んだ理由

1. エディタの見た目が変わらない

markview.nvimはバッファ内でレンダリングするため、Neovimの画面自体が装飾されます。

これに違和感がありました。

  • ソースコードとして編集しているのに、見た目が変わる
  • 「生のマークダウン」を見ながら編集したい
  • 装飾が入ると、記法の確認がしづらい

markdown-preview.nvimなら、エディタはそのまま。 「編集画面」と「プレビュー画面」が明確に分離されていて、頭の切り替えがしやすいです。

2. Mermaid などの高度な表示に対応

これが決め手でした。

markdown-preview.nvimは以下に対応しています:

  • Mermaid — フローチャート、シーケンス図、ガントチャートなど
  • KaTeX — 数式
  • PlantUML — UML図
  • chart.js — グラフ

技術文書を書くときに、Mermaidでフローチャートを描くことが多いので、これは必須でした。

Loading diagram...

こういった図がブラウザでそのままレンダリングされます。

markview.nvimでもMermaid対応はあるようですが、ブラウザでの表示に比べると制限があります。

markdown-preview.nvim のインストールと設定

インストール(lazy.nvim)

Lua
{
  "iamcco/markdown-preview.nvim",
  cmd = { "MarkdownPreviewToggle", "MarkdownPreview", "MarkdownPreviewStop" },
  ft = { "markdown" },
  build = function() vim.fn["mkdp#util#install"]() end,
}

Node.jsとyarnがインストール済みの場合は、build を以下に置き換えることもできます:

Lua(yarn版)
build = "cd app && npx --yes yarn install",

コマンド

Vim script
:MarkdownPreview       " プレビュー開始
:MarkdownPreviewStop   " プレビュー停止
:MarkdownPreviewToggle " プレビューのトグル(開始/停止)

コマンドを実行すると、ローカルにWebSocketサーバーが起動し、自動的にブラウザが開いてプレビューが表示されます。

キーマップ設定

Lua
vim.keymap.set('n', '<Space>mp', ':MarkdownPreviewToggle<CR>', { desc = 'Toggle Markdown Preview' })

<Space>mp でプレビューをトグルできるようにしています。<Plug> マッピングも用意されています:

Vim script
nmap <C-s> <Plug>MarkdownPreview
nmap <M-s> <Plug>MarkdownPreviewStop
nmap <C-p> <Plug>MarkdownPreviewToggle

全オプション一覧

markdown-preview.nvim の設定は vim.g.mkdp_* 変数で行います。以下が全オプションです。

起動・終了

オプションデフォルト説明
mkdp_auto_start0Markdownバッファを開いたとき自動でプレビュー開始
mkdp_auto_close1Markdownバッファから離れたとき自動でプレビュー終了
mkdp_refresh_slow01 にすると保存時・インサート離脱時のみ更新。0 は編集中リアルタイム更新
mkdp_command_for_global01 にするとMarkdown以外のファイルでもコマンドが使える
mkdp_filetypes{'markdown'}プレビュー対象のファイルタイプ

ブラウザ・表示

オプションデフォルト説明
mkdp_browser''プレビューに使うブラウザのパス。空ならシステムデフォルト
mkdp_browserfunc''URLを受け取ってブラウザを開くカスタム関数名
mkdp_themeシステム設定プレビューのテーマ。'dark' または 'light'
mkdp_page_title'「${name}」'プレビューページのタイトル。${name} がファイル名に置換される
mkdp_echo_preview_url01 にするとプレビューURLをコマンドラインに表示

ネットワーク・リモート

オプションデフォルト説明
mkdp_open_to_the_world01 にするとサーバーをネットワークに公開(リモート開発時に便利)
mkdp_open_ip''プレビューページを開くカスタムIP
mkdp_port''サーバーのポート番号。空ならランダム

カスタムスタイル

オプションデフォルト説明
mkdp_markdown_css''カスタムMarkdown CSSファイルの絶対パス
mkdp_highlight_css''カスタムハイライトCSSファイルの絶対パス

複数ファイルプレビュー

オプションデフォルト説明
mkdp_combine_preview01 にすると複数ファイルで同一プレビューウィンドウを再利用
mkdp_combine_preview_auto_refresh1バッファ切替時に自動でプレビュー内容を更新

レンダリングオプション(mkdp_preview_options)

mkdp_preview_options にはレンダリングの詳細設定をテーブルで指定します:

Lua
vim.g.mkdp_preview_options = {
  mkit = {},                    -- markdown-it のオプション
  katex = {},                   -- KaTeX のオプション
  uml = {},                     -- PlantUML のオプション
  maid = {},                    -- Mermaid のオプション
  disable_sync_scroll = 0,      -- 同期スクロール無効化(1で無効)
  sync_scroll_type = 'middle',  -- 'middle' | 'top' | 'relative'
  hide_yaml_meta = 1,           -- YAMLフロントマターを非表示
  sequence_diagrams = {},       -- js-sequence-diagrams のオプション
  flowchart_diagrams = {},      -- flowchart.js のオプション
  content_editable = false,     -- プレビューページの編集可否
  disable_filename = 0,         -- ファイル名ヘッダーの非表示
  toc = {},                     -- 目次のオプション
}

sync_scroll_type の違い:

  • 'middle' — カーソル位置が常にプレビューの中央
  • 'top' — Vimの上端がプレビューの上端に一致
  • 'relative' — カーソルの相対位置をプレビューに反映

設定例:リモート開発でのプレビュー

SSHでリモートサーバーのNeovimを使っている場合、ローカルブラウザでプレビューできます:

Lua
vim.g.mkdp_open_to_the_world = 1
vim.g.mkdp_open_ip = '0.0.0.0'
vim.g.mkdp_port = 8888
vim.g.mkdp_echo_preview_url = 1

この設定で http://<サーバーIP>:8888 にアクセスすればプレビューが見られます。

設定例:ブラウザを新規ウィンドウで開く

デフォルトでは既存のブラウザタブで開きますが、新しいウィンドウで開きたい場合:

Lua(macOS)
vim.g.mkdp_browserfunc = 'OpenMarkdownPreview'
vim.cmd([[
  function OpenMarkdownPreview(url)
    execute "silent ! open -a Firefox -n --args --new-window " . a:url
  endfunction
]])

Firefox の部分を Google\ ChromeBrave\ Browser に変えれば、それぞれのブラウザで開けます。

対応記法と具体例

markdown-preview.nvim は多くの記法をサポートしています。

Mermaid(図・チャート)

フローチャート、シーケンス図、ガントチャートなどを記述できます。

```mermaid
graph LR
    A[ユーザー] --> B[アプリ]
    B --> C[データベース]
    C --> B
    B --> A
```
Loading diagram...

ガントチャートも書けます:

```mermaid
gantt
    dateFormat YYYY-MM-DD
    title プロジェクトスケジュール
    section 設計
    要件定義 :a1, 2025-01-01, 30d
    基本設計 :after a1, 20d
    section 開発
    実装 :2025-02-20, 45d
    テスト :2025-04-06, 15d
```

KaTeX(数式)

インライン数式と数式ブロックに対応しています。

インライン: $E = mc^2$
 
ブロック:
$$
\sum_{i=1}^{n} x_i = x_1 + x_2 + \cdots + x_n
$$

PlantUML(UML図)

シーケンス図やクラス図を記述できます。

```plantuml
Bob -> Alice : hello
Alice -> Bob : hi
```

または @startuml / @enduml 記法も使えます。

Chart.js(グラフ)

JSON形式でグラフを記述できます。

```chart
{
  "type": "pie",
  "data": {
    "labels": ["Red", "Blue", "Yellow"],
    "datasets": [{
      "data": [300, 50, 100],
      "backgroundColor": ["#FF6384", "#36A2EB", "#FFCE56"]
    }]
  }
}
```

シーケンス図(js-sequence-diagrams)

```sequence-diagrams
Andrew->China: Says
Note right of China: China thinks
China-->Andrew: How are you?
Andrew->>China: I am good thanks!
```

Flowchart(flowchart.js)

```flowchart
st=>start: 開始
e=>end: 終了
op1=>operation: 処理
cond=>condition: 条件
 
st->op1->cond
cond(yes)->e
cond(no)->op1
```

dot(Graphviz)

```dot
digraph G {
  A -> B -> C;
  B -> D;
}
```

目次

以下のいずれかをファイル内に記述すると、目次が自動生成されます:

${toc}
[[toc]]
[toc]
[[_toc_]]

画像サイズ指定

通常のMarkdown画像にサイズを指定できます:

![image](path/to/image.png =400x200)

使用感

良い点

  • リアルタイム同期 — 編集すると即座にブラウザに反映(WebSocket接続)
  • スクロール同期 — エディタのカーソル位置とブラウザが連動(3種類の同期モード)
  • 記法の対応幅が広い — Mermaid、KaTeX、PlantUML、Chart.js、Flowchart、dot、シーケンス図
  • ダークテーマ — 目に優しい(ヘッダーにテーマ切替ボタンも隠れている)
  • カスタムCSS — 自分好みのスタイルに変更可能

気になる点

  • ブラウザが必要 — 当たり前だけど、ブラウザが立ち上がる
  • リソース消費 — Node.jsサーバーが常駐するので、多少メモリを使う
  • 同期スクロールがカクつく場合があるupdatetime を小さい値(例:100)に設定すると改善する

とはいえ、常時使うわけではないので問題ありません。 READMEを書くときや、技術文書を整理するときに使っています。

Tips

  • 同期スクロールがラグい場合は set updatetime=100 を設定
  • WSL 2でブラウザが開かない場合は sudo apt-get install -y xdg-utils でインストール
  • ヘッダーにマウスを合わせると、テーマ切替ボタンが表示される

他のプラグインが向いている人

バッファ内レンダリング系(markview.nvim / render-markdown.nvim)

  • バッファ内で完結させたい
  • ブラウザを開きたくない
  • シンプルなマークダウン(見出し、リスト、コードブロック程度)がメイン
  • Neovimの画面が装飾されても気にならない

「ターミナルから出たくない」という人にはこちらの方が合うかもしれません。 render-markdown.nvimはAnti-conceal機能があるので、markview.nvimよりも編集中の違和感が少ないです。

peek.nvim

  • markdown-preview.nvimの機能はオーバースペック
  • Node.jsよりDenoの方が好み
  • GitHub風のプレビューで十分
  • 軽量な方がいい

glow.nvim(アーカイブ済み)

  • ターミナル内で読み取り確認したい
  • 新規プロジェクトでの採用は非推奨(メンテ終了のため)

まとめ

5つのプラグイン比較表

プラグイン表示場所MermaidKaTeXPlantUMLChart.jsカスタムCSS依存
markview.nvimバッファ内限定的Treesitter
render-markdown.nvimバッファ内LaTeXブロックTreesitter
markdown-preview.nvimブラウザ対応対応対応対応対応Node.js
peek.nvimブラウザ対応対応Deno
glow.nvimターミナルglow CLI

markdown-preview.nvim を選んだ理由

  1. エディタの見た目が変わらない — ソースコードとして編集したい
  2. 対応記法が最も豊富 — Mermaid、KaTeX、PlantUML、Chart.js、Flowchart、dot、シーケンス図
  3. カスタマイズ性が高い — CSS変更、リモートプレビュー、ポート指定など

対応記法の豊富さが群を抜いています。技術文書でMermaidやKaTeXを多用するなら、現時点ではこれ一択だと思います。

どのプラグインが合うかは好みの問題ですが、私は「編集画面」と「プレビュー画面」を明確に分けたい派でした。


参考