Home

Awesome

markdown.nvim <!-- toc omit heading -->

Configurable tools for working with markdown files in Neovim.

ci tests (nightly)

markdown-nvim-demo

Contents <!-- toc omit heading -->

Features

Planned features

Requirements

Installation

Install markdown.nvim with your preferred plugin manager.

Getting help

markdown.nvim provides help docs that can be accessed by running :help markdown.nvim.

Configuration

Detailed plugin configuration information can be found in the help doc (:h markdown.configuration).

A call to require("markdown").setup() is necessary for commands and keybindings to be registered in markdown buffers.

A table of configuration options can optionally be passed to the setup() function. Any fields in the table will overwrite the corresponding default. markdown.nvim uses the following defaults:

{
  -- Disable all keymaps by setting mappings field to 'false'.
  -- Selectively disable keymaps by setting corresponding field to 'false'.
  mappings = {
    inline_surround_toggle = "gs", -- (string|boolean) toggle inline style
    inline_surround_toggle_line = "gss", -- (string|boolean) line-wise toggle inline style
    inline_surround_delete = "ds", -- (string|boolean) delete emphasis surrounding cursor
    inline_surround_change = "cs", -- (string|boolean) change emphasis surrounding cursor
    link_add = "gl", -- (string|boolean) add link
    link_follow = "gx", -- (string|boolean) follow link
    go_curr_heading = "]c", -- (string|boolean) set cursor to current section heading
    go_parent_heading = "]p", -- (string|boolean) set cursor to parent section heading
    go_next_heading = "]]", -- (string|boolean) set cursor to next section heading
    go_prev_heading = "[[", -- (string|boolean) set cursor to previous section heading
  },
  inline_surround = {
    -- For the emphasis, strong, strikethrough, and code fields:
    -- * 'key': used to specify an inline style in toggle, delete, and change operations
    -- * 'txt': text inserted when toggling or changing to the corresponding inline style
    emphasis = {
      key = "i",
      txt = "*",
    },
    strong = {
      key = "b",
      txt = "**",
    },
    strikethrough = {
      key = "s",
      txt = "~~",
    },
    code = {
      key = "c",
      txt = "`",
    },
  },
  link = {
    paste = {
      enable = true, -- whether to convert URLs to links on paste
    },
  },
  toc = {
    -- Comment text to flag headings/sections for omission in table of contents.
    omit_heading = "toc omit heading",
    omit_section = "toc omit section",
    -- Cycling list markers to use in table of contents.
    -- Use '.' and ')' for ordered lists.
    markers = { "-" },
  },
  -- Hook functions allow for overriding or extending default behavior.
  -- Called with a table of options and a fallback function with default behavior.
  -- Signature: fun(opts: table, fallback: fun())
  hooks = {
    -- Called when following links. Provided the following options:
    -- * 'dest' (string): the link destination
    -- * 'use_default_app' (boolean|nil): whether to open the destination with default application
    --   (refer to documentation on <Plug> mappings for explanation of when this option is used)
    follow_link = nil,
  },
  on_attach = nil, -- (fun(bufnr: integer)) callback when plugin attaches to a buffer
}

on_attach is useful for creating additional buffer-only keymaps:

on_attach = function(bufnr)
  local map = vim.keymap.set
  local opts = { buffer = bufnr }
  map({ 'n', 'i' }, '<M-l><M-o>', '<Cmd>MDListItemBelow<CR>', opts)
  map({ 'n', 'i' }, '<M-L><M-O>', '<Cmd>MDListItemAbove<CR>', opts)
  map('n', '<M-c>', '<Cmd>MDTaskToggle<CR>', opts)
  map('x', '<M-c>', ':MDTaskToggle<CR>', opts)
end,

markdown.nvim can even be configured to support standard/typical inline style keybindings in visual mode like <C-b> for strong/bold and <C-i> for emphasis/italic:

on_attach = function(bufnr)
  local function toggle(key)
    return "<Esc>gv<Cmd>lua require'markdown.inline'"
      .. ".toggle_emphasis_visual'" .. key .. "'<CR>"
  end

  vim.keymap.set("x", "<C-b>", toggle("b"), { buffer = bufnr })
  vim.keymap.set("x", "<C-i>", toggle("i"), { buffer = bufnr })
end,

<Plug> mappings

markdown.nvim sets up <Plug> mappings regardless of configuration. Most are used by the configuration mappings described above:

<Plug> MappingConfiguration Mapping
<Plug>(markdown_toggle_emphasis)inline_surround_toggle
<Plug>(markdown_toggle_emphasis_line)inline_surround_toggle_line
<Plug>(markdown_toggle_emphasis_visual)inline_surround_toggle
<Plug>(markdown_delete_emphasis)inline_surround_delete
<Plug>(markdown_change_emphasis)inline_surround_change
<Plug>(markdown_add_link)link_add
<Plug>(markdown_add_link_visual)link_add
<Plug>(markdown_follow_link)link_follow
<Plug>(markdown_go_current_heading)go_curr_heading
<Plug>(markdown_go_parent_heading)go_parent_heading
<Plug>(markdown_go_next_heading)go_next_heading
<Plug>(markdown_go_prev_heading)go_prev_heading

The following <Plug> mappings are not used by markdown.nvim's configuration:

<Plug> MappingDescription
<Plug>(markdown_follow_link_default_app)Like <Plug>(markdown_follow_link) but opens links to non-markdown files in the default application for the link destination. The hook follow_link is called before following the link with the option 'use_default_app' set to 'true'.

Usage

Detailed usage instructions can be found in the help doc (:h markdown.usage).

markdown.nvim is broken up into different feature categories:

Inline surround

markdown.nvim provides keymaps to toggle, delete, and change emphasis and code spans, referred to in this section as "styles". The supported styles and the default keys used to refer to them are:

StyleKey
emphasis (typically rendered in italic)"i"
strong (typically rendered in bold)"b"
strikethrough"s"
code span"c"

Table of contents

A table of contents (TOC) is created from the top-level ATX and setext headings of markdown buffers.

The :MDInsertToc [max_level] [markers] command adds a TOC by inserting (normal mode) or replacing selected lines (visual mode). Optional arguments can be provided to set the max heading level to include and the list markers to alternate through for each heading level.

The :MDToc [max_level] and :MDTocAll [max_level] commands show a TOC for the current buffer in the current window's location list. :MDToc omits flagged headings and MDTocAll includes all headings. An optional argument can be provided to set the max heading level to include.

Omit sections and headings <!-- toc omit heading -->

Headings and entire sections can be omitted from the TOC by flagging them with <!-- toc omit heading --> and <!-- toc omit section -->, respectively. The flag can either be placed directly above (i.e., on the line immediately preceding) or within the heading content. For example, the following headings would be omitted:

# heading 1 <!-- toc omit heading -->

<!-- toc omit heading -->
## heading 2

<!-- toc omit section -->
# section heading omitted
## subsection heading also omitted

Lists

Most list editing commands are intended to be invoked by custom keymaps (see notes on the on_attach field under configuration).

Links

Navigation

Markdown buffers can be navigated with the following keymaps:

nvim-treesitter module

<details> <summary><strong>markdown.nvim</strong> can also be configured as an <a href="https://github.com/nvim-treesitter/nvim-treesitter/">nvim-treesitter</a> module.</summary>

Module installation <!-- toc omit heading -->

The following code snippets show how to install markdown.nvim as an nvim-treesitter module. Refer to nvim-treesitter for the appropriate way to install and manage parsers.

Module configuration <!-- toc omit heading -->

When markdown.nvim is configured as an nvim-treesitter module, configuration options are passed to the require("nvim-treesitter.configs").setup() function. All configuration options are the same as described in the configuration section.

local configs = require("nvim-treesitter.configs")

configs.setup({
  ensure_installed = { "markdown", "markdown_inline", --[[ other parsers you need ]] },
  markdown = {
    enable = true, -- must be specified to enable markdown.nvim as a module
    -- configuration here or nothing for defaults
  },
})
</details>