A hackable Markdown, HTML, LaTeX, Typst & YAML previewer for Neovim.
Core features,
- Supports HTML, LaTeX, Markdown, Typst & YAML.
- Highly customisable! Everything is done via the configuration table to ensure maximum customisability.
- Hybrid editing mode! Allows editing & previewing files at the same time.
- Split view! Allows previewing files on a separate window that updates in real-time!
- Partial text wrap support(only for markdown at the moment).
- Dynamic config that allows any option to be a function.
- Dynamic
highlight groups
that automatically updates with the colorscheme.
Expand to see complete feature list
HTML features,

-
Allows customising how various container & void elements are shown.
-
Supports heading elements out of the box.
-
Supports the following container elements out of the box,
<a></a>
<b></b>
<code></code>
<em></em>
<i></i>
<mark></mark>
<strong></strong>
<pre></pre>
<sub></sub>
<sup></sup>
<u></u>
-
Supports the following void elements out of the box,
<hr>
<br>
LaTeX features,

-
Supports the following items,
- Math blocks(typically
$$...$$
) & inline math(typically$...$
). - LaTeX commands.
- Escaped characters.
- Math fonts
- Subscript.
- Superscript.
- Math symbols.
\text{}
.
- Math blocks(typically
-
Supports commonly used math commands out of the box,
\frac{}
\sin{}
\cos{}
\tan{}
\sinh{}
\cosh{}
\tanh{}
\csc{}
\sec{}
\cot{}
\csch{}
\sech{}
\coth{}
\arcsin{}
\arccos{}
\arctan{}
\arg{}
\deg{}
\drt{}
\dim{}
\exp{}
\gcd{}
\hom{}
\inf{}
\ker{}
\lg{}
\lim{}
\liminf{}
\limsup{}
\ln{}
\log{}
\min{}
\max{}
\Pr{}
\sup{}
\sqrt{}
\lvert{}
\lVert{}
\boxed{}
-
Supports the following fonts(requires any modern Unicode font),
default
(Default math font).\mathbb{}
\mathbf{}
\mathbffrak{}
\mathbfit{}
\nathbfscr{}
\mathcal{}
\mathfrak{}
\mathsf{}
\mathsfbf{}
\mathsfbfit{}
\mathsfit{}
\mathtt{}
-
Supports Unicode based subscript & superscript texts.
-
Supports 2056 different math symbol definitions.
Markdown features,

-
Supports the following items,
- Block quotes(with support for
callouts
& titles). - Fenced code blocks.
- Headings(setext & atx).
- Horizontal rules.
- List items(
+
,-
,*
,n.
&n)
). - Minus & plus metadata.
- Reference link definitions.
- Tables.
- Block quotes(with support for
-
wrap
option support for the following items,- Block quotes.
- Headings(when
org_indent
is used). - List items(when
add_padding
is true).
-
Org-mode like indentation for headings.
Markdown inline features,

-
Supports the following items,
- Checkboxes(supports minimal-style checkboxes).
- Email links.
- Entities.
- Escaped characters.
- Footnotes.
- Hyperlinks.
- Images.
- Inline codes/Code spans.
- URI autolinks.
-
Obsidian/PKM extended item support,
- Block reference links.
- Embed file links.
- Internal links(supports aliases).
-
Wide variety of HTML entity names & codes support.
- Supported named entities: 786.
- Supported entity codes: 853.
-
Github emoji shorthands support. Supports 1920 shorthands.
-
Custom configuration based on link patterns.
Typst features,

-
Supports the following items,
- Code blocks.
- Code spans.
- Escaped characters.
- Headings.
- Labels.
- List items(
-
,+
&n.
). - Math blocks.
- Math spans.
- Raw blocks.
- Raw spans.
- Reference links.
- Subscripts.
- Superscripts.
- Symbols.
- Terms.
- URL links.
-
Supports a variety of typst symbols,
- Symbol entries: 932
- Symbol shorthands: 40
-
Supports Unicode based subscript & superscript texts.
YAML features,

-
Custom property icons.
-
Custom property scope decorations.
-
Custom icons(/decorations) based on property type & value(e.g.
booleans
). -
Supports the following properties out of the box,
- tags.
- aliases.
- cssclasses.
- publish.
- permalink.
- description.
- images.
- cover.
Hybrid mode features,
Normal hybrid mode | Linewise hybrid mode |
---|---|
![]() |
![]() |
-
Node-based edit range. Clears the current nodes range of lines. Useful when editing lists, block quotes, code blocks, tables etc.
-
Range-based edit range. Clears the selected number of lines above & below the cursor.
-
Supports multiple cursors to.
Internal Icon provider features,
- 708 different filetype configuration.
- Dynamic highlight groups for matching the colorscheme.
Tracing features,

- You can use
:Markview traceShow
to see what the plugin has been doing(including how long some of them took).
- You can also use
:Markview traceExport
to export these logs.
System,
- Neovim: 0.10.3
Note
It is recommended to use nowrap
(though there is wrap support in the plugin) & expandtab
.
Colorscheme,
- Any tree-sitter based colorscheme is recommended.
External icon providers,
Note
You need to change the config to use the desired icon provider.
{
preview = {
icon_provider = "internal", -- "mini" or "devicons"
}
}
Parsers,
Tip
You can use nvim-treesitter
to easily install parsers. You can install all the parsers with the following command,
:TSInstall markdown markdown_inline html latex typst yaml
Important
On windows, you might need tree-sitter
CLI for the
markdown
markdown_inline
html
(optional)latex
(optional)typst
(optional)yaml
(optional)
Fonts,
- Any modern Unicode font is required for math symbols.
- Nerd fonts are recommended.
Tip
It is recommended to run :checkhealth markview
after installing the plugin to check if any potential issues exist.
Note
This plugin uses tree-sitter
queries. So, it should be loaded before nvim-treesitter
.
Important
This plugin makes use of tree-sitter
queries! So, it must be loaded before nvim-treesitter
.
You can solve this issue by loading this plugin as a dependency of nvim-treesitter
(add dependencies = { "OXY2DEV/markview.nvim" }
to your config for nvim-treesitter in lazy.nvim
) and disable lazy-loading for both of the plugins.
Add this to your plugin list.
Plug "OXY2DEV/markview.nvim"
Warning
Do not lazy load this plugin as it is already lazy-loaded. Lazy-loading may cause more time for the previews to load when starting Neovim!
The plugin should be loaded after your colorscheme to ensure the correct highlight groups are used.
Important
In case you are experiencing syntax issues(e.g. code block markers being hidden), You can use this to load markview.nvim
first by adding it as a dependency of nvim-treesitter
,
{
"nvim-treesitter/nvim-treesitter",
dependencies = { "OXY2DEV/markview.nvim" },
lazy = false,
-- ... All other options.
},
-- For `plugins/markview.lua` users.
return {
"OXY2DEV/markview.nvim",
lazy = false,
-- For `nvim-treesitter` users.
priority = 49,
-- For blink.cmp's completion
-- source
-- dependencies = {
-- "saghen/blink.cmp"
-- },
};
-- For `plugins.lua` users.
{
"OXY2DEV/markview.nvim",
lazy = false,
-- For `nvim-treesitter` users.
priority = 49,
-- For blink.cmp's completion
-- source
-- dependencies = {
-- "saghen/blink.cmp"
-- },
},
local MiniDeps = require("mini.deps");
MiniDeps.add({
source = "OXY2DEV/markview.nvim",
-- For blink.cmp's completion
-- source
-- depends = {
-- "saghen/blink.cmp"
-- },
});
Warning
luarocks package
may sometimes be a bit behind main
.
:Rocks install markview.nvim
Tagged releases can be found in the release page.
Note
Github releases
may sometimes be slightly behind main
.
You can use the dev branch to use test features.
Warning
Development releases can contain breaking changes and experimental changes. Use at your own risk!
return {
"OXY2DEV/markview.nvim",
branch = "dev",
lazy = false
};
-
code span
s don't get recognized when on the line after acode block
(if the line after thecode span
is empty). This is most likely due to some bug in either themarkdown
or themarkdown_inline
parser. -
Incorrect wrapping when setting
wrap
usingmodeline
. This is due totextoff
being 0(instead of the size of thestatuscolumn
) when entering a buffer.
Check the wiki for the entire configuration table. A simplified version is given below.
Click for config jump-scare
--- Configuration table for `markview.nvim`.
---@class mkv.config
---
---@field experimental config.experimental | fun(): config.experimental
---@field highlight_groups { [string]: config.hl } | fun(): { [string]: config.hl }
---@field html config.html | fun(): config.html
---@field latex config.latex | fun(): config.latex
---@field markdown config.markdown | fun(): config.markdown
---@field markdown_inline config.markdown_inline | fun(): config.markdown_inline
---@field preview config.preview | fun(): config.preview
---@field renderers config.renderer[] | fun(): config.renderer[]
---@field typst config.typst | fun(): config.typst
---@field yaml config.yaml | fun(): config.yaml
mkv.config = {
experimental = {
date_formats = {},
date_time_formats = {},
text_filetypes = {},
read_chunk_size = 1000,
link_open_alerts = false,
prefer_nvim = true,
file_open_command = "tabnew",
list_empty_line_tolerance = 3
},
highlight_groups = {},
preview = {
enable = true,
filetypes = { "md", "rmd", "quarto" },
ignore_buftypes = { "nofile" },
ignore_previews = {},
modes = { "n", "no", "c" },
hybrid_modes = {},
debounce = 50,
draw_range = { vim.o.lines, vim.o.lines },
edit_range = { 1, 0 },
callbacks = {},
splitview_winopts = { split = "left" }
},
renderers = {},
html = {
enable = true,
container_elements = {},
headings = {},
void_elements = {},
},
latex = {
enable = true,
blocks = {},
commands = {},
escapes = {},
fonts = {},
inlines = {},
parenthesis = {},
subscripts = {},
superscripts = {},
symbols = {},
texts = {}
},
markdown = {
enable = true,
block_quotes = {},
code_blocks = {},
headings = {},
horizontal_rules = {},
list_items = {},
metadata_plus = {},
metadata_minus = {},
tables = {}
},
markdown_inline = {
enable = true,
block_references = {},
checkboxes = {},
emails = {},
embed_files = {},
entities = {},
escapes = {},
footnotes = {},
highlights = {},
hyperlinks = {},
images = {},
inline_codes = {},
internal_links = {},
uri_autolinks = {}
},
typst = {
enable = true,
codes = {},
escapes = {},
headings = {},
labels = {},
list_items = {},
math_blocks = {},
math_spans = {},
raw_blocks = {},
raw_spans = {},
reference_links = {},
subscripts = {},
superscript = {},
symbols = {},
terms = {},
url_links = {}
},
yaml = {
enable = true,
properties = {}
}
}
This plugin follows the sub-commands approach for creating commands. There is only a single :Markview
command.
It comes with the following sub-commands,
Note
When no sub-command name is provided(or an invalid sub-command is used) :Markview
will run :Markview Toggle
.
Sub-command | Arguments | Description |
---|---|---|
Start |
none | Allows attaching to new buffers. |
Stop |
none | Prevents attaching to new buffers. |
———————————————— | ——————————————————— | ———————————————————————————————————————— |
attach |
buffer, integer | Attaches to buffer. |
detach |
buffer, integer | Detaches from buffer. |
———————————————— | ——————————————————— | ———————————————————————————————————————— |
Enable |
none | Enables preview globally. |
Disable |
none | Disables preview globally. |
Toggle |
none | Toggles preview globally. |
———————————————— | ——————————————————— | ———————————————————————————————————————— |
HybridEnable |
none | Enables hybrid mode. |
HybridDisable |
none | Disables hybrid mode. |
HybridToggle |
none | Toggles hybrid mode. |
———————————————— | ——————————————————— | ———————————————————————————————————————— |
enable |
buffer, integer | Enables preview for buffer. |
disable |
buffer, integer | Disables preview for buffer. |
toggle |
buffer, integer | Toggles preview for buffer. |
———————————————— | ——————————————————— | ———————————————————————————————————————— |
hybridEnable |
buffer, integer | Enables hybrid mode for buffer. |
hybridDisable |
buffer, integer | Disables hybrid mode for buffer. |
hybridToggle |
buffer, integer | Toggles hybrid mode for buffer. |
———————————————— | ——————————————————— | ———————————————————————————————————————— |
linewiseEnable |
none | Enables linewise hybrid mode. |
linewiseDisable |
none | Disables linewise hybrid mode. |
linewiseToggle |
none | Toggles linewise hybrid mode. |
———————————————— | ——————————————————— | ———————————————————————————————————————— |
splitOpen |
buffer, integer | Opens splitview for buffer. |
splitClose |
none | Closes any open splitview. |
splitToggle |
none | Toggles splitview. |
splitRedraw |
none | Updates splitview contents. |
———————————————— | ——————————————————— | ———————————————————————————————————————— |
Render |
none | Updates preview of all active buffers. |
Clear |
none | Clears preview of all active buffer. |
———————————————— | ——————————————————— | ———————————————————————————————————————— |
render |
buffer, integer | Renders preview for buffer. |
clear |
buffer, integer | Clears preview for buffer. |
———————————————— | ——————————————————— | ———————————————————————————————————————— |
toggleAll |
none | Deprecated version of Toggle . |
enableAll |
none | Deprecated version of Enable . |
disableAll |
none | Deprecated version of Disable . |
———————————————— | ——————————————————— | ———————————————————————————————————————— |
traceExport |
none | Exports trace logs to trace.txt . |
traceShow |
none | Shows trace logs in a window. |
Tip
buffer defaults to the current buffer. So, you can run commands on the current buffer without providing the buffer.
:Markview toggle "Toggles preview of the current buffer.
markview.nvim
emits various autocmd events during different parts of the rendering allowing users to extend the plugin's functionality.
vim.api.nvim_create_autocmd("User", {
pattern = "MarkviewAttach",
callback = function (event)
--- This will have all the data you need.
local data = event.data;
vim.print(data);
end
})
Note
Autocmds are executed after callbacks!
Currently emitted autocmds are,
-
MarkviewAttach Called when attaching to a buffer.
Arguments,
-
buffer
, integer The buffer that's being attached to. -
windows
, integer[] List of windows attached tobuffer
.
-
-
MarkviewDetach Called when detaching from a buffer.
Arguments,
-
buffer
, integer The buffer that's being detached from. -
windows
, integer[] List of windows attached tobuffer
.
-
-
MarkviewDisable Called when disabling previews in a buffer.
Arguments,
-
buffer
, integer The buffer whose the preview was disabled. -
windows
, integer[] List of windows attached tobuffer
.
-
-
MarkviewEnable Called when enabling previews in a buffer.
Arguments,
-
buffer
, integer The buffer whose the preview was enabled. -
windows
, integer[] List of windows attached tobuffer
.
-
-
MarkviewSplitviewClose Called when the splitview window is closed. Called before splitview is closed.
Arguments,
-
source
, integer The buffer whose contents are being shown. -
preview_buffer
, integer The buffer that's showing the preview. -
preview_window
, integer The window where thepreview_buffer
is being shown.
-
-
MarkviewSplitviewOpen Called when the splitview window is opened.
Arguments,
-
source
, integer The buffer whose contents are being shown. -
preview_buffer
, integer The buffer that's showing the preview. -
preview_window
, integer The window where thepreview_buffer
is being shown.
-
You can find more details on highlight groups here. The following highlight groups are created by the plugin,
Note
The value of these groups are updated when changing the colorscheme!
-
MarkviewPalette0
, has a background & foreground. -
MarkviewPalette0Fg
, only the foreground -
MarkviewPalette0Bg
, only the background. -
MarkviewPalette0Sign
, background of the sign column(LineNr
) & foreground. -
MarkviewPalette1
-
MarkviewPalette1Fg
-
MarkviewPalette1Bg
-
MarkviewPalette1Sign
-
MarkviewPalette2
-
MarkviewPalette2Fg
-
MarkviewPalette2Bg
-
MarkviewPalette2Sign
-
MarkviewPalette3
-
MarkviewPalette3Fg
-
MarkviewPalette3Bg
-
MarkviewPalette3Sign
-
MarkviewPalette4
-
MarkviewPalette4Fg
-
MarkviewPalette4Bg
-
MarkviewPalette4Sign
-
MarkviewPalette5
-
MarkviewPalette5Fg
-
MarkviewPalette5Bg
-
MarkviewPalette5Sign
-
MarkviewPalette6
-
MarkviewPalette6Fg
-
MarkviewPalette6Bg
-
MarkviewPalette6Sign
-
MarkviewCode
. -
MarkviewCodeInfo
. -
MarkviewCodeFg
. -
MarkviewInlineCode
.
Note
These groups are meant to create a gradient!
MarkviewGradient0
MarkviewGradient1
MarkviewGradient2
MarkviewGradient3
MarkviewGradient4
MarkviewGradient5
MarkviewGradient6
MarkviewGradient7
MarkviewGradient8
MarkviewGradient9
-
MarkviewBlockQuoteDefault
, links toMarkviewPalette0Fg
. -
MarkviewBlockQuoteError
, links toMarkviewPalette1Fg
. -
MarkviewBlockQuoteNote
, links toMarkviewPalette5Fg
. -
MarkviewBlockQuoteOk
, links toMarkviewPalette4Fg
. -
MarkviewBlockQuoteSpecial
, links toMarkviewPalette3Fg
. -
MarkviewBlockQuoteWarn
, links toMarkviewPalette2Fg
. -
MarkviewCheckboxCancelled
, links toMarkviewPalette0Fg
. -
MarkviewCheckboxChecked
, links toMarkviewPalette4Fg
. -
MarkviewCheckboxPending
, links toMarkviewPalette2Fg
. -
MarkviewCheckboxProgress
, links toMarkviewPalette6Fg
. -
MarkviewCheckboxUnchecked
, links toMarkviewPalette1Fg
. -
MarkviewCheckboxStriked
, links toMarkviewPalette0Fg
1. -
MarkviewIcon0
, links toMarkviewPalette0Fg
2. -
MarkviewIcon1
, links toMarkviewPalette1Fg
2. -
MarkviewIcon2
, links toMarkviewPalette2Fg
2. -
MarkviewIcon3
, links toMarkviewPalette3Fg
2. -
MarkviewIcon4
, links toMarkviewPalette4Fg
2. -
MarkviewIcon5
, links toMarkviewPalette5Fg
2. -
MarkviewIcon6
, links toMarkviewPalette6Fg
2. -
MarkviewHeading1
, links toMarkviewPalette1
. -
MarkviewHeading2
, links toMarkviewPalette2
. -
MarkviewHeading3
, links toMarkviewPalette3
. -
MarkviewHeading4
, links toMarkviewPalette4
. -
MarkviewHeading5
, links toMarkviewPalette5
. -
MarkviewHeading6
, links toMarkviewPalette6
. -
MarkviewHeading1Sign
, links toMarkviewPalette1Sign
. -
MarkviewHeading2Sign
, links toMarkviewPalette2Sign
. -
MarkviewHeading3Sign
, links toMarkviewPalette3Sign
. -
MarkviewHeading4Sign
, links toMarkviewPalette4Sign
. -
MarkviewHeading5Sign
, links toMarkviewPalette5Sign
. -
MarkviewHeading6Sign
, links toMarkviewPalette6Sign
. -
MarkviewHyperlink
, links to@markup.link.label.markdown_inline
. -
MarkviewImage
, links to@markup.link.label.markdown_inline
. -
MarkviewEmail
, links to@markup.link.url.markdown_inline
. -
MarkviewSubscript
, links toMarkviewPalette3Fg
. -
MarkviewSuperscript
, links toMarkviewPalette6Fg
. -
MarkviewListItemMinus
, links toMarkviewPalette2Fg
. -
MarkviewListItemPlus
, links toMarkviewPalette4Fg
. -
MarkviewListItemStar
, links toMarkviewPalette6Fg
. -
MarkviewTableHeader
, links to@markup.heading.markdown
. -
MarkviewTableBorder
, links toMarkviewPalette5Fg
. -
MarkviewTableAlignLeft
, links to@markup.heading.markdown
. -
MarkviewTableAlignCenter
, links to@markup.heading.markdown
. -
MarkviewTableAlignRight
, links to@markup.heading.markdown
.
Important
Presets are looking for contributors!
If you have any custom configuration that you would like to have as a preset you can open a pull request
for that.
Check the wiki page for more information.
local presets = require("markview.presets");
require("markview").setup({
markdown = {
headings = presets.headings.slanted
}
});
Currently available presets are,
Accessed using require("markview.presets").headings
.
-
glow
Like the headings in theGlow
CLI app. -
glow_center
Centered version ofglow
. -
slanted
Heading level + slanted tail. -
arrowed
Heading level + arrowed tail. -
simple
Headings similar to headings in some books. -
marker
Simple marker for heading level.
Accessed using require("markview.presets").horizontal_rules
.
-
thin
Simple line. -
thick
Slightly thicker line. -
double
Double lines. -
dashed
Dashed line. -
dotted
Dotted line. -
solid
Very thick line. -
arrowed
Arrowed line.
Accessed using require("markview.presets").tables
.
-
none
Border-less table(kinda like the ones used in some help files). -
single
Single border table. -
double
Double border table. -
rounded
Single border with rounded edges(default). -
solid
Solid border table.
markview.nvim
comes with a few extra things for added functionality. Currently available modules are,
-
checkboxes.lua Checkbox toggle, state change & more! Supports visual mode too with checkbox state caching! Wiki section
-
editor.lua A simple
code block
creator & editor with support for nested elements! Wiki section -
headings.lua Simple heading level changer with support for
setext
headings. Wiki section
Example usage,
-- Load the checkboxes module.
require("markview.extras.checkboxes").setup();
Go over a line with a checkbox and run,
:Checkbox interactive
Now use h
, j
, k
, l
to change the checkbox state.
If you have time and want to make this project better, consider helping me fix any of these issues,
- Add support for more filetypes in the internal icon provider.
- Optimization of
require("markview.renderers.markdown").output()
. - Optimization of the table renderer.
- Stricter logic to reduce preview redraws.
- Make
splitview
update as little content as possible. - Make the help files/wiki more beginner friendly.