btv.markdown
btv.markdown.render(src)
btv.markdown.render(src) -> { lines = {string,..}, highlights = { hl, .. }, fills = { fill, .. }, code = { block, .. } }
Parse src (CommonMark + GFM: tables, strikethrough, task lists) into stripped
display lines with the markup syntax removed (**bold** -> bold, # Title ->
Title, ``` fences dropped, - x -> • x, > q -> ▎ q, - [ ] -> ☐),
plus the styling to paint over them. Each highlight is a table:
{ line = <1-based line>, col_start = <1-based char col>,
col_end = <exclusive char col>, group = "<@markup.* capture>" }
Columns are CHARACTER columns (not bytes), so they index lines[hl.line] the way
Lua string.sub / display code counts. group is a neovim @markup.* treesitter
capture (@markup.strong, @markup.heading.1, @markup.raw, @markup.link.label,
@markup.quote, @markup.list, …), so a colorscheme that styles treesitter
markdown styles these identically.
fills are row rules — a thematic break (---) or a GFM table’s header separator:
each { line = <1-based>, char = "─", group = "<@markup.*>" } means “repeat char
from the end of lines[line]’s text to the right edge”. Those lines are blank, so
the rule spans the row; render it as a run out to your surface’s width.
code are the fenced code blocks, each
{ first_line = <1-based>, last_line = <1-based, inclusive>, lang = "<fence language>"? }
— lang is absent for a bare ``` fence. Use it to back a block as a code region
(set line_hl_group = "@markup.raw.block" on first_line..last_line — the doc-float
look) or to syntax-highlight its body in lang.
Pure and infallible: unsupported constructs still contribute their text.
Defined in markdown.lua.
btv.markdown.to_view(src, opts)
btv.markdown.to_view(src[, opts]) -> { lines = {string,..}, decor = { mark, .. } }
Turn markdown src into view-ready content: the display lines plus the decor
extmarks that style them — exactly the { lines, decor } shape an btv.view.component
render returns (or hand lines to view:set_lines and decor to view:set_decor).
The higher-level companion to btv.markdown.render: render gives the raw pieces,
to_view assembles them into something you can drop straight onto a surface.
- Prose is rendered: the stripped lines, styled with
render’s@markup.*spans (as rangedhl_groupextmarks in byte columns). - Thematic breaks / table separators become a full-line rule glyph.
- Fenced code blocks are LEFT as raw
```fences (so tree-sitter can highlight them — see below), backed with a full-widthline_hl_groupcode background, and their fence delimiter lines are hidden behind a blankingvirt_textoverlay so the block reads as rendered.
IMPORTANT — code-block syntax highlighting: the fences are kept on purpose. Mount the
surface with filetype = "markdown" (e.g.
btv.view.component{...}:mount{ filetype = "markdown", … }) so the markdown grammar’s
injections highlight each fenced block in its own language. Without that filetype the
code still shows (backed, fences hidden) but unhighlighted. Per-language highlighting
needs that language’s grammar installed.
opts (all optional):
rule_width(default 80): cells a thematic-break / table-separator rule spans.code_hl_group(default"@markup.raw.block"): the code-block background group.
Pure Lua over btv.markdown.render; no editor state, so it runs on every build.
Defined in markdown.lua.