Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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 ranged hl_group extmarks 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-width line_hl_group code background, and their fence delimiter lines are hidden behind a blanking virt_text overlay 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.