Home

Awesome

<p align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/logo/mkdnflow_logo_dark.png"> <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/logo/mkdnflow_logo_light.png"> <img alt="Black mkdnflow logo in light color mode and white logo in dark color mode." src="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/logo/mkdnflow_logo_light.png"> </picture> </p> <p align=center><img src="https://img.shields.io/badge/Lua-2C2D72?style=for-the-badge&logo=lua&logoColor=white"> <img src="https://img.shields.io/badge/Markdown-000000?style=for-the-badge&logo=markdown&logoColor=white"> <img src="https://img.shields.io/badge/NeoVim-%2357A143.svg?&style=for-the-badge&logo=neovim&logoColor=white"></p> <p align=center> <a href="#-features">Features</a> / <a href="#-installation-and-usage">Installation</a> / <a href="#-starting-a-notebook">Starting a notebook</a> / <a href="#%EF%B8%8F-configuration">Config</a> / <a href="#-commands-and-default-mappings">Commands & mappings</a> / <a href="#%EF%B8%8F-to-do">To do</a> / <a href="#-recent-changes">Recent changes</a> / <a href="#-links">Links</a> </p>

🆕 Latest features and announcements

  1. Custom and customizable foldtext for section folds
  2. Improved table formatting and formatting style options
  3. Customize "jump patterns" for link jumping
  4. Completion of file links and bib-based references (for nvim-cmp)

Announcements

12/12/23: Mkdnflow no longer requires the luautf8 lua rock as a dependency. UTF-8 characters can be used as custom to-do symbols out of the box, and table formatting will work out of the box when the table contains UTF-8 characters.

📝 Description

Mkdnflow is designed for the fluent navigation of documents and notebooks (AKA "wikis") written in markdown. The plugin's flexibility and its prioritization of markdown also means it can become part of your webdev workflow if you use static site generators like Jekyll or Hugo, which can generate static sites from markdown documents.

The plugin is an extended set of functions and mappings to those functions which make it easy to navigate and manipulate markdown documents and notebooks in Neovim. I originally started writing Mkdnflow to replicate some features from Vimwiki in Lua instead of Vimscript, but my current goal for this project is to make this plugin as useful as possible for anyone using Neovim who maintains a set of markdown notes and wishes to efficiently navigate those notes and keep them organized and connected. The plugin now includes some convenience features I wished Vimwiki had, including functionality to rename the source part of a link and its associated file simultaneously.

I keep tabs on the project's issues and appreciate feature requests, suggestions, and bug reports. I invite you to use the discussion board if you would like to share your config, share how Mkdnflow fits into your workflow, get help with setup, or contribute feature suggestions or optimizations. Contributions to the plugin are welcome: fork this repo and submit a pull request with your changes or additions. For Lua resources, see this page or call :h lua or :h api in Neovim.

⚡ Requirements

➖ Differences from Vimwiki

✨ Features

<p align=center> <a href="https://user-images.githubusercontent.com/45184202/166573700-62cdec3b-a13f-4f9e-9d72-ab2650205042.mp4"><img src="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/demo/demo.mp4.png" width="75%"></a> </p>

Markdown or wiki link styles

Follow links and citations

@misc{dschrute,
    url={https://dundermifflin.slack.com/archives/P07BFJD82}
}

Templates for new files

Example template

In the following example, {{ date }} will be filled in based on the result of evaluating the date function at the exact moment one tries to follow a link. {{ filename }} will be filled in based on the result of evaluating the filename function after the new buffer has been opened (thereby inserting the filename of the newly-opened buffer, rather than the previous one).

new_file_template = {
    template = [[
# {{ title }}
Date: {{ date }}
Filename: {{ filename }}
]],
    placeholders = {
        before = {
            date = function()
                return os.date("%A, %B %d, %Y") -- Wednesday, March 1, 2023
            end
        },
        after = {
            filename = function()
                return vim.api.nvim_buf_get_name(0)
            end
        }
    }
}

Customizable link interpretation

Create, customize, and destroy links

require('mkdnflow').setup({
    links = {
        transform_explicit = function(text)
            -- Make lowercase, remove spaces, and reverse the string
            return string.lower(text:gsub(' ', ''))
        end
    }
})

Jump to links, headings, and arbitrary pattern matches

🆕 Completion for nvim-cmp

To enable completion via cmp using the provided source, add mkdnflow as one of the sources in your cmp setup function.

cmp.setup({
	sources = cmp.config.sources({
		-- Other cmp sources
		{ name = 'mkdnflow' },  -- Add this
		-- Other cmp sources
	}),
})

Also, don't forget to edit your formatting options in cmp.setup.

NOTE: There may be some compatibility issues with the completion module and links.transform_explicit/links.transform_implicit functions:

To prevent this, make sure you write sensible transformation functions, preferably using it for folder organization. The other solution is to do a full text search in all the files for links.

Credit: We heavily referenced cmp-pandoc-references and code from other completion sources when writing the cmp module.

Create missing directories

Rename link sources and files simultaneously

Backward and forward navigation through buffers

Keybindings

Manipulate headings

Section folding

Object typeNameemoji iconnerdfont iconplain icon
Tabletbl📈<picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/tbl_dark.png"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/tbl.png"><img src="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/tbl.png" width="18"></picture>
Unordered (bulleted) listul*️⃣<picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/ul_dark.png"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/ul.png"><img src="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/ul.png" width="18"></picture>
Ordered (numbered) listol1️⃣<picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/ol_dark.png"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/ol.png"><img src="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/ol.png" width="18"></picture>
To-do listtodo<picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/todo_dark.png"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/todo.png"><img src="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/todo.png" width="18"></picture>
Imageimg🖼️<picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/img_dark.png"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/img.png"><img src="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/img.png" width="18"></picture>
Fenced code blockfncblk🧮<picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/fncblk_dark.png"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/fncblk.png"><img src="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/fncblk.png" width="18"></picture>
Sectionsec🏷️<picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/sec_dark.png"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/sec.png"><img src="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/sec.png" width="18"></picture>§
Paragraphpar📃<picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/par_dark.png"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/par.png"><img src="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/par.png" width="18"></picture>
Linklink🔗<picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/link_dark.png"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/link.png"><img src="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/nerdfont/link.png" width="18"></picture>

Lists

require('mkdnflow').setup({
    mappings = {
        MkdnEnter = {{'i', 'n', 'v'}, '<CR>'} -- This monolithic command has the aforementioned
            -- insert-mode-specific behavior and also will trigger row jumping in tables. Outside
            -- of lists and tables, it behaves as <CR> normally does.
        -- MkdnNewListItem = {'i', '<CR>'} -- Use this command instead if you only want <CR> in
            -- insert mode to add a new list item (and behave as usual outside of lists).
    }
})

Tables

Disable unused modules

YAML block parsing

Specify one bib source:

---
bib: /home/user/Documents/Library/library.bib
---

Specify multiple bib sources:

---
bib:
  - /home/user/Documents/Library/library.bib
  - /home/user/Projects/special_project/refs.bib
---

📦 Installation and usage

init.lua

<details> <summary>Install with <a href="https://github.com/folke/lazy.nvim">Lazy</a></summary><p>
require('lazy').setup({
    -- Your other plugins
    {
        'jakewvincent/mkdnflow.nvim',
        config = function()
            require('mkdnflow').setup({
                -- Config goes here; leave blank for defaults
            })
        end
    }
    -- Your other plugins
})
</p></details> <details> <summary>Install with <a href="https://github.com/lewis6991/pckr.nvim">Pckr</a></summary><p>
require('pckr').add({
    -- Your other plugins
    {
        'jakewvincent/mkdnflow.nvim',
        config = function()
            require('mkdnflow').setup({
                -- Config goes here; leave blank for defaults
            })
        end
    }
    -- Your other plugins
})
</p></details> <details> <summary>Install with <a href="https://github.com/savq/paq-nvim">Paq</a></summary><p>
require('paq')({
    -- Your other plugins
    'jakewvincent/mkdnflow.nvim',
    -- Your other plugins
})

-- Include the setup function somewhere else in your init.lua/vim file, or the
-- plugin won't activate itself:

require('mkdnflow').setup({
    -- Config goes here; leave blank for defaults
})
</p></details> <details> <summary>Install with <a href="https://github.com/wbthomason/packer.nvim">Packer</a></summary><p>
use({'jakewvincent/mkdnflow.nvim',
     config = function()
        require('mkdnflow').setup({
            -- Config goes here; leave blank for defaults
        })
     end
})
</p></details>

init.vim

<details> <summary>Install with Vim-Plug, NeoBundle, Vundle, Pathogen, or Dein</summary><p>
" Vim-Plug
Plug 'jakewvincent/mkdnflow.nvim'

" NeoBundle
NeoBundle 'jakewvincent/mkdnflow.nvim'

" Vundle
Bundle 'jakewvincent/mkdnflow.nvim'

" Pathogen
git clone https://github.com/jakewvincent/mkdnflow.nvim.git ~/.vim/bundle/mkdownflow.nvim

" Dein
call dein#add('jakewvincent/mkdnflow.nvim')

" Include the setup function somewhere else in your init.vim file, or the
" plugin won't activate itself:
lua << EOF
require('mkdnflow').setup({
    -- Config goes here; leave blank for defaults
})
EOF
</p></details>

❗ Caveats/warnings

All functionality of the plugin should now work on all operating systems, including Windows! However, since I don't use Windows on my daily driver, there may be edge cases that cause trouble. Please file an issue if anything comes up.

🏁 Starting a notebook

As long as you successfully installed Mkdnflow, you don't need to do anything special to start using the plugin. All of the plugin's features will be enabled for any markdown file (or for any filetype you specify under the filetypes config key). If you would like to start a notebook (AKA "wiki"), first create a directory for it. If you're using Neovim in the terminal, simply enter nvim index.md and start writing. I suggest using index.md as a landing page/table of contents that contains links to all other notes in your notebook. If you use such a landing page, try setting perspective.priority in your Mkdnflow config to 'root' and your perspective.root_tell to 'index.md' so that Mkdnflow can identify your notebook's root directory and reliably interpret links relative to this directory.

⚙️ Configuration

Currently, the setup function uses the defaults shown below. See the descriptions and non-default options in the section below the following block. To use these defaults, simply pass no arguments setup function: require('mkdnflow').setup(). To change these settings, specify new values for any of them them in the setup function.

-- ** DEFAULT SETTINGS; TO USE THESE, PASS NO ARGUMENTS TO THE SETUP FUNCTION **
require('mkdnflow').setup({
    modules = {
        bib = true,
        buffers = true,
        conceal = true,
        cursor = true,
        folds = true,
        foldtext = true,
        links = true,
        lists = true,
        maps = true,
        paths = true,
        tables = true,
        yaml = false,
        cmp = false
    },
    filetypes = {md = true, rmd = true, markdown = true},
    create_dirs = true,
    perspective = {
        priority = 'first',
        fallback = 'current',
        root_tell = false,
        nvim_wd_heel = false,
        update = false
    },
    wrap = false,
    bib = {
        default_path = nil,
        find_in_root = true
    },
    silent = false,
    cursor = {
        jump_patterns = nil
    },
    links = {
        style = 'markdown',
        name_is_source = false,
        conceal = false,
        context = 0,
        implicit_extension = nil,
        transform_implicit = false,
        transform_explicit = function(text)
            text = text:gsub(" ", "-")
            text = text:lower()
            text = os.date('%Y-%m-%d_')..text
            return(text)
        end,
        create_on_follow_failure = true
    },
    new_file_template = {
        use_template = false,
        placeholders = {
            before = {
                title = "link_title",
                date = "os_date"
            },
            after = {}
        },
        template = "# {{ title }}"
    },
    to_do = {
        symbols = {' ', '-', 'X'},
        update_parents = true,
        not_started = ' ',
        in_progress = '-',
        complete = 'X'
    },
    foldtext = {
        object_count = true,
        object_count_icons = 'emoji',
        object_count_opts = function()
            return require('mkdnflow').foldtext.default_count_opts()
        end,
        line_count = true,
        line_percentage = true,
        word_count = false,
        title_transformer = nil,
        separator = ' · ',
        fill_chars = {
            left_edge = '⢾',
            right_edge = '⡷',
            left_inside = ' ⣹',
            right_inside = '⣏ ',
            middle = '⣿',
        },
    },
    tables = {
        trim_whitespace = true,
        format_on_move = true,
        auto_extend_rows = false,
        auto_extend_cols = false,
        style = {
            cell_padding = 1,
            separator_padding = 1,
            outer_pipes = true,
            mimic_alignment = true
        }
    },
    yaml = {
        bib = { override = false }
    },
    mappings = {
        MkdnEnter = {{'n', 'v'}, '<CR>'},
        MkdnTab = false,
        MkdnSTab = false,
        MkdnNextLink = {'n', '<Tab>'},
        MkdnPrevLink = {'n', '<S-Tab>'},
        MkdnNextHeading = {'n', ']]'},
        MkdnPrevHeading = {'n', '[['},
        MkdnGoBack = {'n', '<BS>'},
        MkdnGoForward = {'n', '<Del>'},
        MkdnCreateLink = false, -- see MkdnEnter
        MkdnCreateLinkFromClipboard = {{'n', 'v'}, '<leader>p'}, -- see MkdnEnter
        MkdnFollowLink = false, -- see MkdnEnter
        MkdnDestroyLink = {'n', '<M-CR>'},
        MkdnTagSpan = {'v', '<M-CR>'},
        MkdnMoveSource = {'n', '<F2>'},
        MkdnYankAnchorLink = {'n', 'yaa'},
        MkdnYankFileAnchorLink = {'n', 'yfa'},
        MkdnIncreaseHeading = {'n', '+'},
        MkdnDecreaseHeading = {'n', '-'},
        MkdnToggleToDo = {{'n', 'v'}, '<C-Space>'},
        MkdnNewListItem = false,
        MkdnNewListItemBelowInsert = {'n', 'o'},
        MkdnNewListItemAboveInsert = {'n', 'O'},
        MkdnExtendList = false,
        MkdnUpdateNumbering = {'n', '<leader>nn'},
        MkdnTableNextCell = {'i', '<Tab>'},
        MkdnTablePrevCell = {'i', '<S-Tab>'},
        MkdnTableNextRow = false,
        MkdnTablePrevRow = {'i', '<M-CR>'},
        MkdnTableNewRowBelow = {'n', '<leader>ir'},
        MkdnTableNewRowAbove = {'n', '<leader>iR'},
        MkdnTableNewColAfter = {'n', '<leader>ic'},
        MkdnTableNewColBefore = {'n', '<leader>iC'},
        MkdnFoldSection = {'n', '<leader>f'},
        MkdnUnfoldSection = {'n', '<leader>F'}
    }
})

Config descriptions

modules (dictionary-like table)

create_dirs (boolean)

perspective (dictionary-like table)

filetypes (dictionary-like table)

NOTE: This functionality references the file's extension. It does not rely on Neovim's filetype recognition. The extension must be provided in lower case because the plugin converts file names to lowercase. Any arbitrary extension can be supplied. Setting an extension to false is the same as not including it in the list.

wrap (boolean)

bib (dictionary-like table)

silent (boolean)

cursor (dictionary-like table)

links (dictionary-like table)

function(input)
    return(string.upper(os.date('%Y-')..input))
end
function(input)
    if input:match('%d%d%d%d%-%d%d%-%d%d') then
        return('journals/'..input)
    else
        return('pages/'..input)
    end
end

new_file_template (dictionary-like table)

to_do (dictionary-like table)

foldtext (dictionary-like table)

-- SAMPLE FOLDTEXT CONFIGURATION RECIPE WITH COMMENTS
require('mkdnflow').setup({
    -- Other config options
    foldtext = {
        title_transformer = function()
            local function my_title_transformer(text)
                local updated_title = text:gsub('%b{}', '')
                updated_title = updated_title:gsub('^%s*', '')
                updated_title = updated_title:gsub('%s*$', '')
                updated_title = updated_title:gsub('^######', '░░░░░▓')
                updated_title = updated_title:gsub('^#####', '░░░░▓▓')
                updated_title = updated_title:gsub('^####', '░░░▓▓▓')
                updated_title = updated_title:gsub('^###', '░░▓▓▓▓')
                updated_title = updated_title:gsub('^##', '░▓▓▓▓▓')
                updated_title = updated_title:gsub('^#', '▓▓▓▓▓▓')
                return updated_title
            end
            return my_title_transformer
        end,
        object_count_icon_set = 'nerdfont', -- Use/fall back on the nerdfont icon set
        object_count_opts = function()
            local opts = {
                link = false, -- Prevent links from being counted
                blockquote = { -- Count block quotes (these aren't counted by default)
                    icon = ' ',
                    count_method = {
                        pattern = { '^>.+$' },
                        tally = 'blocks',
                    }
                },
                fncblk = {
                    -- Override the icon for fenced code blocks with 
                    icon = ' '
                }
            }
            return opts
        end,
        line_count = false, -- Prevent lines from being counted
        word_count = true, -- Count the words in the section
        fill_chars = {
            left_edge = '╾─🖿 ─',
            right_edge = '──╼',
            item_separator = ' · ',
            section_separator = ' // ',
            left_inside = ' ┝',
            right_inside = '┥ ',
            middle = '─',
        },
    },
    -- Other config options
})

The above recipe will produce foldtext like the following (for an h3-level section heading called My section):

<p align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/foldtext/foldtext_ex_dark.png"> <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/foldtext/foldtext_ex.png"> <img src="https://raw.githubusercontent.com/jakewvincent/mkdnflow.nvim/readme-media/assets/foldtext/foldtext_ex.png"> </picture> </p>

tables (dictionary-like table)

yaml (dictionary-like table)

mappings (dictionary-like table)

NOTE: <name of command> should be the name of a commands defined in mkdnflow.nvim/plugin/mkdnflow.lua (see :h Mkdnflow-commands for a list).

👍 Recommended vim settings

I recommended turning on autowriteall in Neovim for markdown filetypes. This will ensure that changes to buffers are saved when you navigate away from that buffer, e.g. by following a link to another file. See :h awa. If you have hidden enabled or if a buffer is hidden by bufhidden, you may need to use the second option (thanks, @vandalt).

-- If you have an init.lua
vim.api.nvim_create_autocmd("FileType", {pattern = "markdown", command = "set awa"})
-- Use the following if your buffer is set to become hidden
--vim.api.nvim_create_autocmd("BufLeave", {pattern = "*.md", command = "silent! wall"})
" If you have an init.vim
autocmd FileType markdown set autowriteall
" Use the following if your buffer is set to become hidden
autocmd BufLeave *.md silent! wall

❕ Commands and default mappings

These default mappings can be disabled; see Configuration. Commands with no mappings trigger functions that are called by the functions with mappings, but I've given them a command name so you can use them as independent functions if you'd like to.

KeymapModeCommandDescription
<CR>n, v(, i):MkdnEnter<CR>Triggers a wrapper function which will (a) infer your editor mode, and then if in normal or visual mode, either follow a link, create a new link from the word under the cursor or visual selection, or fold a section (if cursor is on a section heading); if in insert mode, it will create a new list item (if cursor is in a list), go to the next row in a table (if cursor is in a table), or behave normally (if cursor is not in a list or a table) NOTE: There is no insert-mode mapping for this command by default since some may find its effects intrusive. To enable the insert-mode functionality, add to the mappings table: MkdnEnter = {{'i', 'n', 'v'}, '<CR>}
<Tab>n:MkdnNextLink<CR>Move cursor to the beginning of the next link (if there is a next link)
<S-Tab>n:MkdnPrevLink<CR>Move the cursor to the beginning of the previous link (if there is one)
]]n:MkdnNextHeading<CR>Move the cursor to the beginning of the next heading (if there is one)
[[n:MkdnPrevHeading<CR>Move the cursor to the beginning of the previous heading (if there is one)
<BS>n:MkdnGoBack<CR>Open the historically last-active buffer in the current window
<Del>n:MkdnGoForward<CR>Open the buffer that was historically navigated away from in the current window
----:MkdnCreateLink<CR>Create a link from the word under the cursor (in normal mode) or from the visual selection (in visual mode)
<leader>pn, v:MkdnCreateLinkFromClipboard<CR>Create a link, using the content from the system clipboard (e.g. a URL) as the source and the word under cursor or visual selection as the link text
----:MkdnFollowLink<CR>Open the link under the cursor, creating missing directories if desired, or if there is no link under the cursor, make a link from the word under the cursor
<M-CR>n:MkdnDestroyLink<CR>Destroy the link under the cursor, replacing it with just the text from [...]
<M-CR>v:MkdnTagSpan<CR>Tag a visually-selected span of text with an ID, allowing it to be linked to with an anchor link
<F2>n:MkdnMoveSource<CR>Open a dialog where you can provide a new source for a link and the plugin will rename and move the associated file on the backend (and rename the link source)
yaan:MkdnYankAnchorLink<CR>Yank a formatted anchor link (if cursor is currently on a line with a heading)
yfan:MkdnYankFileAnchorLink<CR>Yank a formatted anchor link with the filename included before the anchor (if cursor is currently on a line with a heading)
+n:MkdnIncreaseHeading<CR>Increase heading importance (remove hashes)
-n:MkdnDecreaseHeading<CR>Decrease heading importance (add hashes)
<C-Space>n:MkdnToggleToDo<CR>Toggle to-do list item's completion status or convert a list item into a to-do list item
<leader>nnn:MkdnUpdateNumbering<CR>Update numbering for all siblings of the list item of the current line
----:MkdnNewListItem<CR>Add a new ordered list item, unordered list item, or (uncompleted) to-do list item
on:MkdnNewListItemBelowInsert<CR>Add a new ordered list item, unordered list item, or (uncompleted) to-do list item below the current line and begin insert mode. Add a new line and enter insert mode when the cursor is not in a list.
On:MkdnNewListItemAboveInsert<CR>Add a new ordered list item, unordered list item, or (uncompleted) to-do list item above the current line and begin insert mode. Add a new line and enter insert mode when the cursor is not in a list.
----:MkdnExtendList<CR>Like above, but the cursor stays on the current line (new list items of the same typ are added below)
----:MkdnTable ncol nrow (noh)Make a table of ncol columns and nrow rows. Pass 'noh' as a third argument to exclude table headers.
----:MkdnTableFormat<CR>Format a table under the cursor
<Tab>i:MkdnTableNextCell<CR>Move the cursor to the beginning of the next cell in the table, jumping to the next row if needed
<S-Tab>i:MkdnTablePrevCell<CR>Move the cursor to the beginning of the previous cell in the table, jumping to the previous row if needed
<leader>irn:MkdnTableNewRowBelow<CR>Add a new row below the row the cursor is currently in
<leader>iRn:MkdnTableNewRowAbove<CR>Add a new row above the row the cursor is currently in
<leader>icn:MkdnTableNewColAfter<CR>Add a new column following the column the cursor is currently in
<leader>iCn:MkdnTableNewColBefore<CR>Add a new column before the column the cursor is currently in
----:MkdnTab<CR>Wrapper function which will jump to the next cell in a table (if cursor is in a table) or indent an (empty) list item (if cursor is in a list item)
----:MkdnSTab<CR>Wrapper function which will jump to the previous cell in a table (if cursor is in a table) or de-indent an (empty) list item (if cursor is in a list item)
<leader>f--:MkdnFoldSection<CR>Fold the section the cursor is currently on/in
<leader>F--:MkdnUnfoldSection<CR>Unfold the folded section the cursor is currently on
----:Mkdnflow<CR>Manually start Mkdnflow

Miscellaneous notes (+ troubleshooting) on remapping

☑️ To do

<details> <summary>Completed to-dos</summary><p> </p></details>

🔧 Recent changes

<details> <summary>Older changes (> 1 month ago)</summary><p>
if not require('mkdnflow').buffers.goBack() then
  vim.cmd('Dirvish %:p')
end
</p></details>

🔗 Links

To complement mkdnflow

Alternatives to mkdnflow