From cd202c27e61239af5b95d6a6b984f40f1d98340c Mon Sep 17 00:00:00 2001 From: Shawon Date: Wed, 31 Dec 2025 22:16:41 +0600 Subject: [PATCH 01/31] feat(parsers): Added `doctext` parser --- lua/markview/parser.lua | 1 + lua/markview/parsers/doctext.lua | 123 +++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 lua/markview/parsers/doctext.lua diff --git a/lua/markview/parser.lua b/lua/markview/parser.lua index fa73912..0c8aaab 100644 --- a/lua/markview/parser.lua +++ b/lua/markview/parser.lua @@ -99,6 +99,7 @@ parser.init = function (buffer, from, to, cache) ---|fS local _parsers = { + doctext = require("markview.parsers.doctext"); markdown = require("markview.parsers.markdown"); markdown_inline = require("markview.parsers.markdown_inline"); html = require("markview.parsers.html"); diff --git a/lua/markview/parsers/doctext.lua b/lua/markview/parsers/doctext.lua new file mode 100644 index 0000000..6e72c30 --- /dev/null +++ b/lua/markview/parsers/doctext.lua @@ -0,0 +1,123 @@ +--- HTML parser for `markview.nvim`. +local doctext = {}; + +--- Queried contents +---@type table[] +doctext.content = {}; + +--- Queried contents, but sorted +---@type { [string]: table } +doctext.sorted = {} + +--- Wrapper for `table.insert()`. +---@param data table +doctext.insert = function (data) + table.insert(doctext.content, data); + + if not doctext.sorted[data.class] then + doctext.sorted[data.class] = {}; + end + + table.insert(doctext.sorted[data.class], data); +end + +--- Tasks. +---@param buffer integer +---@param TSNode table +---@param text string[] +---@param range markview.parsed.range +doctext.task = function (buffer, TSNode, text, range) +end + +--- HTML parser +---@param buffer integer +---@param TSTree table +---@param from integer? +---@param to integer? +---@return markview.parsed.doctext[] +---@return markview.parsed.doctext_sorted +doctext.parse = function (buffer, TSTree, from, to) + -- Clear the previous contents + doctext.sorted = {}; + doctext.content = {}; + + local scanned_queries = vim.treesitter.query.parse("doctext", [[ + (task) @doctext.task + + (task_scope + (_) @doctext.scope) + + (code_block) @doctext.code_block + + (double_quote) @doctext.double_quote + (issue_reference) @doctext.issue + (mention) @doctext.mention + (url) @doctext.url + (autolink) @doctext.autolink + (taglink) @doctext.taglink + + (comment) @doctext.comment + ]]); + + for capture_id, capture_node, _, _ in scanned_queries:iter_captures(TSTree:root(), buffer, from, to) do + local capture_name = scanned_queries.captures[capture_id]; + + if not capture_name:match("^doctext%.") then + goto continue; + end + + ---@type string? + local capture_text = vim.treesitter.get_node_text(capture_node, buffer); + local r_start, c_start, r_end, c_end = capture_node:range(); + + if capture_text == nil then + goto continue; + end + + if not capture_text:match("\n$") then + capture_text = capture_text .. "\n"; + end + + local lines = {}; + + for line in capture_text:gmatch("(.-)\n") do + table.insert(lines, line); + end + + ---@type boolean, string + local success, error = pcall( + doctext[capture_name:gsub("^doctext%.", "")], + + buffer, + capture_node, + lines, + { + row_start = r_start, + col_start = c_start, + + row_end = r_end, + col_end = c_end + } + ); + + if success == false then + require("markview.health").print({ + kind = "ERR", + + from = "parsers/doctext.lua", + fn = "parse()", + + message = { + { tostring(error), "DiagnosticError" } + } + }); + end + + ::continue:: + end + + return doctext.content, doctext.sorted; +end + +return doctext; + From 9c4a9a4de1f488e2d5777dfd9dc8531d47f40e10 Mon Sep 17 00:00:00 2001 From: Shawon Date: Thu, 1 Jan 2026 09:29:28 +0600 Subject: [PATCH 02/31] feat(doctext): Added configuration for `doctext` --- lua/markview/config/doctext.lua | 35 +++++++++++++++++++++++++++++++++ lua/markview/spec.lua | 3 ++- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 lua/markview/config/doctext.lua diff --git a/lua/markview/config/doctext.lua b/lua/markview/config/doctext.lua new file mode 100644 index 0000000..f313f74 --- /dev/null +++ b/lua/markview/config/doctext.lua @@ -0,0 +1,35 @@ +return { + enable = true, + + tasks = { + default = { + padding_left = " ", + padding_right = " ", + + icon = "󰋽 ", + + hl = "MarkviewPalette1", + }, + }, + + issues = { + default = { + padding_left = " ", + padding_right = " ", + + icon = "󰋽 ", + + hl = "MarkviewPalette6", + }, + }, + mentions = { + default = { + padding_left = " ", + padding_right = " ", + + icon = "󰋽 ", + + hl = "MarkviewPalette6", + }, + }, +}; diff --git a/lua/markview/spec.lua b/lua/markview/spec.lua index f69294c..e68ae22 100644 --- a/lua/markview/spec.lua +++ b/lua/markview/spec.lua @@ -187,7 +187,7 @@ spec.default = { debounce = 150, icon_provider = "internal", - filetypes = { "markdown", "quarto", "rmd", "typst" }, + filetypes = { "markdown", "quarto", "rmd", "typst", "doctext", }, ignore_buftypes = { "nofile" }, raw_previews = {}, @@ -210,6 +210,7 @@ spec.default = { ---@type string[] Properties that should be sourced *externally*. spec.__external_config = { + "doctext", "html", "markdown", "markdown_inline", From 46587f58654933ea3f12d8ac1c289eee29287902 Mon Sep 17 00:00:00 2001 From: Shawon Date: Thu, 1 Jan 2026 09:30:11 +0600 Subject: [PATCH 03/31] feat(doctext): Added `task` renderer feat(doctext): Added issue support feat(doctext): Added mention support --- lua/markview/parsers/doctext.lua | 49 ++++- lua/markview/renderer.lua | 4 + lua/markview/renderers/doctext.lua | 251 +++++++++++++++++++++++ lua/markview/types/parsers/doctext.lua | 30 +++ lua/markview/types/renderers/doctext.lua | 13 ++ 5 files changed, 345 insertions(+), 2 deletions(-) create mode 100644 lua/markview/renderers/doctext.lua create mode 100644 lua/markview/types/parsers/doctext.lua create mode 100644 lua/markview/types/renderers/doctext.lua diff --git a/lua/markview/parsers/doctext.lua b/lua/markview/parsers/doctext.lua index 6e72c30..2fca1da 100644 --- a/lua/markview/parsers/doctext.lua +++ b/lua/markview/parsers/doctext.lua @@ -23,10 +23,55 @@ end --- Tasks. ---@param buffer integer ----@param TSNode table +---@param TSNode TSNode ---@param text string[] ----@param range markview.parsed.range +---@param range markview.parsed.doctext.task.range doctext.task = function (buffer, TSNode, text, range) + local kind = TSNode:field("type")[1]; + + for child in TSNode:iter_children() do + if child:type() == ":" then + _, _, range.label_row_end, range.label_col_end = child:range(); + end + end + + if not kind then + return; + end + + range.kind = { kind:range(); }; + + doctext.insert({ + class = "doctext_task", + kind = vim.treesitter.get_node_text(kind, buffer, {}), + + text = text, + range = range, + }); +end + +--- Issue. +---@param text string[] +---@param range markview.parsed.range +doctext.issue = function (_, _, text, range) + doctext.insert({ + class = "doctext_issue", + + text = text, + range = range, + }); +end + +--- Issue. +---@param text string[] +---@param range markview.parsed.range +doctext.mention = function (_, _, text, range) + doctext.insert({ + class = "doctext_mention", + + text = text, + range = range, + }); end --- HTML parser diff --git a/lua/markview/renderer.lua b/lua/markview/renderer.lua index 41fbcc9..af61cdb 100644 --- a/lua/markview/renderer.lua +++ b/lua/markview/renderer.lua @@ -15,6 +15,9 @@ renderer.__filter_cache = { renderer.option_maps = { ---|fS + doxtext = { + tasks = { "doctext_task" }, + }, html = { container_elements = { "html_container_element" }, headings = { "html_heading" }, @@ -356,6 +359,7 @@ renderer.render = function (buffer, parsed_content) ---|fS local _renderers = { + doctext = require("markview.renderers.doctext"), html = require("markview.renderers.html"), markdown = require("markview.renderers.markdown"), markdown_inline = require("markview.renderers.markdown_inline"), diff --git a/lua/markview/renderers/doctext.lua b/lua/markview/renderers/doctext.lua new file mode 100644 index 0000000..2efec7b --- /dev/null +++ b/lua/markview/renderers/doctext.lua @@ -0,0 +1,251 @@ +local doctext = {}; + +local utils = require("markview.utils"); +local spec = require("markview.spec"); + +doctext.ns = vim.api.nvim_create_namespace("markview/doctext"); + +---@param buffer integer +---@param item markview.parsed.doctext.tasks +doctext.task = function (buffer, item) + ---|fS + + ---@type markview.config.doctext.tasks? + local main_config = spec.get({ "doctext", "tasks" }, { fallback = nil }); + + if not main_config then + return; + end + + ---@type markview.config.doctext.tasks.opts? + local config = utils.match(main_config, item.kind, { + ignore_keys = { "enable" }, + eval_args = { buffer, item } + }); + + if not config then + return; + end + + local range = item.range; + local row_end = range.label_row_end or range.kind[3]; + local col_end = range.label_col_end or range.kind[4]; + + vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.kind[1], range.kind[2], { + undo_restore = false, invalidate = true, + end_row = row_end, + end_col = col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, doctext.ns, row_end, col_end - 1, { + undo_restore = false, invalidate = true, + end_col = col_end, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + if config.desc_hl then + vim.api.nvim_buf_set_extmark(buffer, doctext.ns, row_end, col_end, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.desc_hl) + }); + end + + ---|fE +end + +---@param buffer integer +---@param item markview.parsed.doctext.tasks +doctext.issue = function (buffer, item) + ---|fS + + ---@type markview.config.doctext.tasks? + local main_config = spec.get({ "doctext", "issues" }, { fallback = nil }); + + if not main_config then + return; + end + + ---@type markview.config.doctext.tasks.opts? + local config = utils.match(main_config, item.text[1] or "", { + ignore_keys = { "enable" }, + eval_args = { buffer, item } + }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.row_end, range.col_end, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + +---@param buffer integer +---@param item markview.parsed.doctext.tasks +doctext.mention = function (buffer, item) + ---|fS + + ---@type markview.config.doctext.tasks? + local main_config = spec.get({ "doctext", "mentions" }, { fallback = nil }); + + if not main_config then + return; + end + + ---@type markview.config.doctext.tasks.opts? + local config = utils.match(main_config, item.text[1] or "", { + ignore_keys = { "enable" }, + eval_args = { buffer, item } + }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.row_end, range.col_end, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + +--- Renders HTML elements +---@param buffer integer +---@param content markview.parsed.doctext[] +doctext.render = function (buffer, content) + doctext.cache = { + font_regions = {}, + style_regions = { + superscripts = {}, + subscripts = {} + }, + }; + + local custom = spec.get({ "renderers" }, { fallback = {} }); + + for _, item in ipairs(content or {}) do + local success, err; + + if custom[item.class] then + success, err = pcall(custom[item.class], doctext.ns, buffer, item); + else + success, err = pcall(doctext[item.class:gsub("^doctext_", "")], buffer, item); + end + + if success == false then + require("markview.health").print({ + kind = "ERR", + + from = "renderers/doctext.lua", + fn = "render() -> " .. item.class, + + message = { + { tostring(err), "DiagnosticError" } + } + }); + end + end +end + +--- Clears decorations of HTML elements +---@param buffer integer +---@param from integer +---@param to integer +doctext.clear = function (buffer, from, to) + vim.api.nvim_buf_clear_namespace(buffer, doctext.ns, from or 0, to or -1); +end + +return doctext; diff --git a/lua/markview/types/parsers/doctext.lua b/lua/markview/types/parsers/doctext.lua new file mode 100644 index 0000000..101cbfa --- /dev/null +++ b/lua/markview/types/parsers/doctext.lua @@ -0,0 +1,30 @@ +---@meta + +------------------------------------------------------------------------------ + +--- A `task`. +---@class markview.parsed.doctext.tasks +--- +---@field class "doctext_task" +--- +---@field kind string Type of task(e.g. `feat`, `TODO` etc.) +---@field text string +---@field range markview.parsed.doctext.task.range + + +---@class markview.parsed.doctext.task.range +--- +---@field label_row_end? integer End row of a label(A label may be like `foo:`, `bar(topic):`). +---@field label_col_end? integer End column of a label(A label may be like `foo:`, `bar(topic):`). +--- +---@field kind integer[] Range of the `task kind`(result of `{ TSNode:range() }`). +--- +---@field row_start integer +---@field row_end integer +---@field col_start integer +---@field col_end integer + +------------------------------------------------------------------------------ + +---@alias markview.parsed.doctext +---| markview.parsed.doctext.tasks diff --git a/lua/markview/types/renderers/doctext.lua b/lua/markview/types/renderers/doctext.lua new file mode 100644 index 0000000..aab7896 --- /dev/null +++ b/lua/markview/types/renderers/doctext.lua @@ -0,0 +1,13 @@ +---@meta + +------------------------------------------------------------------------------ + +---@class markview.config.doctext.tasks +--- +---@field enable boolean +--- +---@field default markview.config.doctext.tasks.opts +---@field [string] markview.config.doctext.tasks.opts + + +---@alias markview.config.doctext.tasks.opts markview.config.__inline From 8507306405e5d3766a26ce3b163931401b89a36b Mon Sep 17 00:00:00 2001 From: Shawon Date: Thu, 1 Jan 2026 10:10:33 +0600 Subject: [PATCH 04/31] doc(doctext): Updated types --- lua/markview/parsers/doctext.lua | 2 +- lua/markview/renderers/doctext.lua | 12 ++---------- lua/markview/types/parsers/doctext.lua | 22 ++++++++++++++++++++-- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/lua/markview/parsers/doctext.lua b/lua/markview/parsers/doctext.lua index 2fca1da..278a2d0 100644 --- a/lua/markview/parsers/doctext.lua +++ b/lua/markview/parsers/doctext.lua @@ -25,7 +25,7 @@ end ---@param buffer integer ---@param TSNode TSNode ---@param text string[] ----@param range markview.parsed.doctext.task.range +---@param range markview.parsed.doctext.tasks.range doctext.task = function (buffer, TSNode, text, range) local kind = TSNode:field("type")[1]; diff --git a/lua/markview/renderers/doctext.lua b/lua/markview/renderers/doctext.lua index 2efec7b..830c79f 100644 --- a/lua/markview/renderers/doctext.lua +++ b/lua/markview/renderers/doctext.lua @@ -81,7 +81,7 @@ doctext.task = function (buffer, item) end ---@param buffer integer ----@param item markview.parsed.doctext.tasks +---@param item markview.parsed.doctext.issues doctext.issue = function (buffer, item) ---|fS @@ -142,7 +142,7 @@ doctext.issue = function (buffer, item) end ---@param buffer integer ----@param item markview.parsed.doctext.tasks +---@param item markview.parsed.doctext.mentions doctext.mention = function (buffer, item) ---|fS @@ -206,14 +206,6 @@ end ---@param buffer integer ---@param content markview.parsed.doctext[] doctext.render = function (buffer, content) - doctext.cache = { - font_regions = {}, - style_regions = { - superscripts = {}, - subscripts = {} - }, - }; - local custom = spec.get({ "renderers" }, { fallback = {} }); for _, item in ipairs(content or {}) do diff --git a/lua/markview/types/parsers/doctext.lua b/lua/markview/types/parsers/doctext.lua index 101cbfa..89bfd03 100644 --- a/lua/markview/types/parsers/doctext.lua +++ b/lua/markview/types/parsers/doctext.lua @@ -9,10 +9,10 @@ --- ---@field kind string Type of task(e.g. `feat`, `TODO` etc.) ---@field text string ----@field range markview.parsed.doctext.task.range +---@field range markview.parsed.doctext.tasks.range ----@class markview.parsed.doctext.task.range +---@class markview.parsed.doctext.tasks.range --- ---@field label_row_end? integer End row of a label(A label may be like `foo:`, `bar(topic):`). ---@field label_col_end? integer End column of a label(A label may be like `foo:`, `bar(topic):`). @@ -24,6 +24,24 @@ ---@field col_start integer ---@field col_end integer + +--- An issue reference. +---@class markview.parsed.doctext.issues +--- +---@field class "doctext_issue" +--- +---@field text string +---@field range markview.parsed.range + + +--- A mention. +---@class markview.parsed.doctext.mentions +--- +---@field class "doctext_mention" +--- +---@field text string +---@field range markview.parsed.range + ------------------------------------------------------------------------------ ---@alias markview.parsed.doctext From 0d815a8c73d8da9aae19731a984ab84f12097953 Mon Sep 17 00:00:00 2001 From: Shawon Date: Thu, 1 Jan 2026 10:11:03 +0600 Subject: [PATCH 05/31] fix(doctext): `@` in mentions are now hidden --- lua/markview/renderers/doctext.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lua/markview/renderers/doctext.lua b/lua/markview/renderers/doctext.lua index 830c79f..6da91e3 100644 --- a/lua/markview/renderers/doctext.lua +++ b/lua/markview/renderers/doctext.lua @@ -167,6 +167,8 @@ doctext.mention = function (buffer, item) vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.row_start, range.col_start, { undo_restore = false, invalidate = true, + end_col = range.col_start + 1, + conceal = "", virt_text_pos = "inline", virt_text = { From e363a3940c87ad2de4b7f9ae992c7b2c5781f4aa Mon Sep 17 00:00:00 2001 From: Shawon Date: Thu, 1 Jan 2026 23:35:30 +0600 Subject: [PATCH 06/31] refactor(doctext): Updated parser name --- .../config/{doctext.lua => comment.lua} | 7 + lua/markview/parser.lua | 2 +- lua/markview/parsers/comment.lua | 257 ++++++++++++++++++ lua/markview/parsers/doctext.lua | 168 ------------ lua/markview/renderer.lua | 4 +- .../renderers/{doctext.lua => comment.lua} | 125 ++++++--- lua/markview/spec.lua | 2 +- .../parsers/{doctext.lua => comment.lua} | 29 +- lua/markview/types/renderers/comment.lua | 35 +++ lua/markview/types/renderers/doctext.lua | 13 - 10 files changed, 412 insertions(+), 230 deletions(-) rename lua/markview/config/{doctext.lua => comment.lua} (80%) create mode 100644 lua/markview/parsers/comment.lua delete mode 100644 lua/markview/parsers/doctext.lua rename lua/markview/renderers/{doctext.lua => comment.lua} (57%) rename lua/markview/types/parsers/{doctext.lua => comment.lua} (60%) create mode 100644 lua/markview/types/renderers/comment.lua delete mode 100644 lua/markview/types/renderers/doctext.lua diff --git a/lua/markview/config/doctext.lua b/lua/markview/config/comment.lua similarity index 80% rename from lua/markview/config/doctext.lua rename to lua/markview/config/comment.lua index f313f74..40a9818 100644 --- a/lua/markview/config/doctext.lua +++ b/lua/markview/config/comment.lua @@ -1,6 +1,13 @@ return { enable = true, + inline_codes = { + padding_left = " ", + padding_right = " ", + + hl = "MarkviewInlineCode", + }, + tasks = { default = { padding_left = " ", diff --git a/lua/markview/parser.lua b/lua/markview/parser.lua index 0c8aaab..aa7a82b 100644 --- a/lua/markview/parser.lua +++ b/lua/markview/parser.lua @@ -99,7 +99,7 @@ parser.init = function (buffer, from, to, cache) ---|fS local _parsers = { - doctext = require("markview.parsers.doctext"); + comment = require("markview.parsers.comment"); markdown = require("markview.parsers.markdown"); markdown_inline = require("markview.parsers.markdown_inline"); html = require("markview.parsers.html"); diff --git a/lua/markview/parsers/comment.lua b/lua/markview/parsers/comment.lua new file mode 100644 index 0000000..e875161 --- /dev/null +++ b/lua/markview/parsers/comment.lua @@ -0,0 +1,257 @@ +--- HTML parser for `markview.nvim`. +local comment = {}; + +--- Queried contents +---@type table[] +comment.content = {}; + +--- Queried contents, but sorted +---@type { [string]: table } +comment.sorted = {} + +--- Wrapper for `table.insert()`. +---@param data table +comment.insert = function (data) + table.insert(comment.content, data); + + if not comment.sorted[data.class] then + comment.sorted[data.class] = {}; + end + + table.insert(comment.sorted[data.class], data); +end + +--- Tasks. +---@param buffer integer +---@param TSNode TSNode +---@param text string[] +---@param range markview.parsed.comment.tasks.range +comment.task = function (buffer, TSNode, text, range) + local kind = TSNode:field("type")[1]; + + for child in TSNode:iter_children() do + if child:type() == ":" then + _, _, range.label_row_end, range.label_col_end = child:range(); + end + end + + if not kind then + return; + end + + range.kind = { kind:range(); }; + + comment.insert({ + class = "comment_task", + kind = vim.treesitter.get_node_text(kind, buffer, {}), + + text = text, + range = range, + }); +end + +--- Issue. +---@param text string[] +---@param range markview.parsed.range +comment.task_scope = function (_, _, text, range) + comment.insert({ + class = "comment_task_scope", + + text = text, + range = range, + }); +end + +--- Issue. +---@param text string[] +---@param range markview.parsed.range +comment.inline_code = function (_, _, text, range) + comment.insert({ + class = "comment_inline_code", + + text = text, + range = range, + }); +end + +--- Issue. +---@param buffer integer +---@param TSNode TSNode +---@param text string[] +---@param range markview.parsed.range +comment.code_block = function (buffer, TSNode, text, range) + local lang = TSNode:field("type")[1]; + local language; + + if lang then + language = vim.treesitter.get_node_text(lang, buffer, {}); + end + + comment.insert({ + class = "comment_code_block", + language = language, + + text = text, + range = range, + }); +end + +--- Issue. +---@param text string[] +---@param range markview.parsed.range +comment.issue = function (_, _, text, range) + comment.insert({ + class = "comment_issue", + + text = text, + range = range, + }); +end + +--- Issue. +---@param text string[] +---@param range markview.parsed.range +comment.mention = function (_, _, text, range) + comment.insert({ + class = "comment_mention", + + text = text, + range = range, + }); +end + +--- Issue. +---@param text string[] +---@param range markview.parsed.range +comment.url = function (_, _, text, range) + comment.insert({ + class = "comment_url", + + text = text, + range = range, + }); +end + +--- Issue. +---@param text string[] +---@param range markview.parsed.range +comment.autolink = function (_, _, text, range) + comment.insert({ + class = "comment_autolink", + + text = text, + range = range, + }); +end + +--- Issue. +---@param text string[] +---@param range markview.parsed.range +comment.taglink = function (_, _, text, range) + comment.insert({ + class = "comment_taglink", + + text = text, + range = range, + }); +end + +--- HTML parser +---@param buffer integer +---@param TSTree table +---@param from integer? +---@param to integer? +---@return markview.parsed.comment[] +---@return markview.parsed.comment_sorted +comment.parse = function (buffer, TSTree, from, to) + -- Clear the previous contents + comment.sorted = {}; + comment.content = {}; + + local scanned_queries; + + if pcall(vim.treesitter.query.parse, "comment", "(source) @test") then + scanned_queries = vim.treesitter.query.parse("comment", [[ + (tag) @comment.tag ; Task. + (uri) @comment.url + ]]); + else + scanned_queries = vim.treesitter.query.parse("comment", [[ + (task) @comment.task + + (task_scope + (word) @comment.task_scope) + + (code) @comment.inline_code + (code_block) @comment.code_block + + (issue_reference) @comment.issue + (mention) @comment.mention + (url) @comment.url + (autolink) @comment.autolink + (taglink) @comment.taglink + ]]); + end + + for capture_id, capture_node, _, _ in scanned_queries:iter_captures(TSTree:root(), buffer, from, to) do + local capture_name = scanned_queries.captures[capture_id]; + + if not capture_name:match("^comment%.") then + goto continue; + end + + ---@type string? + local capture_text = vim.treesitter.get_node_text(capture_node, buffer); + local r_start, c_start, r_end, c_end = capture_node:range(); + + if capture_text == nil then + goto continue; + end + + if not capture_text:match("\n$") then + capture_text = capture_text .. "\n"; + end + + local lines = {}; + + for line in capture_text:gmatch("(.-)\n") do + table.insert(lines, line); + end + + ---@type boolean, string + local success, error = pcall( + comment[capture_name:gsub("^comment%.", "")], + + buffer, + capture_node, + lines, + { + row_start = r_start, + col_start = c_start, + + row_end = r_end, + col_end = c_end + } + ); + + if success == false then + require("markview.health").print({ + kind = "ERR", + + from = "parsers/comment.lua", + fn = "parse()", + + message = { + { tostring(error), "DiagnosticError" } + } + }); + end + + ::continue:: + end + + return comment.content, comment.sorted; +end + +return comment; + diff --git a/lua/markview/parsers/doctext.lua b/lua/markview/parsers/doctext.lua deleted file mode 100644 index 278a2d0..0000000 --- a/lua/markview/parsers/doctext.lua +++ /dev/null @@ -1,168 +0,0 @@ ---- HTML parser for `markview.nvim`. -local doctext = {}; - ---- Queried contents ----@type table[] -doctext.content = {}; - ---- Queried contents, but sorted ----@type { [string]: table } -doctext.sorted = {} - ---- Wrapper for `table.insert()`. ----@param data table -doctext.insert = function (data) - table.insert(doctext.content, data); - - if not doctext.sorted[data.class] then - doctext.sorted[data.class] = {}; - end - - table.insert(doctext.sorted[data.class], data); -end - ---- Tasks. ----@param buffer integer ----@param TSNode TSNode ----@param text string[] ----@param range markview.parsed.doctext.tasks.range -doctext.task = function (buffer, TSNode, text, range) - local kind = TSNode:field("type")[1]; - - for child in TSNode:iter_children() do - if child:type() == ":" then - _, _, range.label_row_end, range.label_col_end = child:range(); - end - end - - if not kind then - return; - end - - range.kind = { kind:range(); }; - - doctext.insert({ - class = "doctext_task", - kind = vim.treesitter.get_node_text(kind, buffer, {}), - - text = text, - range = range, - }); -end - ---- Issue. ----@param text string[] ----@param range markview.parsed.range -doctext.issue = function (_, _, text, range) - doctext.insert({ - class = "doctext_issue", - - text = text, - range = range, - }); -end - ---- Issue. ----@param text string[] ----@param range markview.parsed.range -doctext.mention = function (_, _, text, range) - doctext.insert({ - class = "doctext_mention", - - text = text, - range = range, - }); -end - ---- HTML parser ----@param buffer integer ----@param TSTree table ----@param from integer? ----@param to integer? ----@return markview.parsed.doctext[] ----@return markview.parsed.doctext_sorted -doctext.parse = function (buffer, TSTree, from, to) - -- Clear the previous contents - doctext.sorted = {}; - doctext.content = {}; - - local scanned_queries = vim.treesitter.query.parse("doctext", [[ - (task) @doctext.task - - (task_scope - (_) @doctext.scope) - - (code_block) @doctext.code_block - - (double_quote) @doctext.double_quote - (issue_reference) @doctext.issue - (mention) @doctext.mention - (url) @doctext.url - (autolink) @doctext.autolink - (taglink) @doctext.taglink - - (comment) @doctext.comment - ]]); - - for capture_id, capture_node, _, _ in scanned_queries:iter_captures(TSTree:root(), buffer, from, to) do - local capture_name = scanned_queries.captures[capture_id]; - - if not capture_name:match("^doctext%.") then - goto continue; - end - - ---@type string? - local capture_text = vim.treesitter.get_node_text(capture_node, buffer); - local r_start, c_start, r_end, c_end = capture_node:range(); - - if capture_text == nil then - goto continue; - end - - if not capture_text:match("\n$") then - capture_text = capture_text .. "\n"; - end - - local lines = {}; - - for line in capture_text:gmatch("(.-)\n") do - table.insert(lines, line); - end - - ---@type boolean, string - local success, error = pcall( - doctext[capture_name:gsub("^doctext%.", "")], - - buffer, - capture_node, - lines, - { - row_start = r_start, - col_start = c_start, - - row_end = r_end, - col_end = c_end - } - ); - - if success == false then - require("markview.health").print({ - kind = "ERR", - - from = "parsers/doctext.lua", - fn = "parse()", - - message = { - { tostring(error), "DiagnosticError" } - } - }); - end - - ::continue:: - end - - return doctext.content, doctext.sorted; -end - -return doctext; - diff --git a/lua/markview/renderer.lua b/lua/markview/renderer.lua index af61cdb..2e7a332 100644 --- a/lua/markview/renderer.lua +++ b/lua/markview/renderer.lua @@ -16,7 +16,7 @@ renderer.option_maps = { ---|fS doxtext = { - tasks = { "doctext_task" }, + tasks = { "comment_task" }, }, html = { container_elements = { "html_container_element" }, @@ -359,7 +359,7 @@ renderer.render = function (buffer, parsed_content) ---|fS local _renderers = { - doctext = require("markview.renderers.doctext"), + comment = require("markview.renderers.comment"), html = require("markview.renderers.html"), markdown = require("markview.renderers.markdown"), markdown_inline = require("markview.renderers.markdown_inline"), diff --git a/lua/markview/renderers/doctext.lua b/lua/markview/renderers/comment.lua similarity index 57% rename from lua/markview/renderers/doctext.lua rename to lua/markview/renderers/comment.lua index 6da91e3..9e627ee 100644 --- a/lua/markview/renderers/doctext.lua +++ b/lua/markview/renderers/comment.lua @@ -1,23 +1,23 @@ -local doctext = {}; +local comment = {}; local utils = require("markview.utils"); local spec = require("markview.spec"); -doctext.ns = vim.api.nvim_create_namespace("markview/doctext"); +comment.ns = vim.api.nvim_create_namespace("markview/comment"); ---@param buffer integer ----@param item markview.parsed.doctext.tasks -doctext.task = function (buffer, item) +---@param item markview.parsed.comment.tasks +comment.task = function (buffer, item) ---|fS - ---@type markview.config.doctext.tasks? - local main_config = spec.get({ "doctext", "tasks" }, { fallback = nil }); + ---@type markview.config.comment.tasks? + local main_config = spec.get({ "comment", "tasks" }, { fallback = nil }); if not main_config then return; end - ---@type markview.config.doctext.tasks.opts? + ---@type markview.config.comment.tasks.opts? local config = utils.match(main_config, item.kind, { ignore_keys = { "enable" }, eval_args = { buffer, item } @@ -31,7 +31,7 @@ doctext.task = function (buffer, item) local row_end = range.label_row_end or range.kind[3]; local col_end = range.label_col_end or range.kind[4]; - vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.row_start, range.col_start, { + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { undo_restore = false, invalidate = true, virt_text_pos = "inline", @@ -45,7 +45,7 @@ doctext.task = function (buffer, item) hl_mode = "combine" }); - vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.kind[1], range.kind[2], { + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.kind[1], range.kind[2], { undo_restore = false, invalidate = true, end_row = row_end, end_col = col_end, @@ -53,7 +53,7 @@ doctext.task = function (buffer, item) hl_group = utils.set_hl(config.hl) }); - vim.api.nvim_buf_set_extmark(buffer, doctext.ns, row_end, col_end - 1, { + vim.api.nvim_buf_set_extmark(buffer, comment.ns, row_end, col_end - 1, { undo_restore = false, invalidate = true, end_col = col_end, conceal = "", @@ -68,7 +68,7 @@ doctext.task = function (buffer, item) }); if config.desc_hl then - vim.api.nvim_buf_set_extmark(buffer, doctext.ns, row_end, col_end, { + vim.api.nvim_buf_set_extmark(buffer, comment.ns, row_end, col_end, { undo_restore = false, invalidate = true, end_row = range.row_end, end_col = range.col_end, @@ -81,18 +81,18 @@ doctext.task = function (buffer, item) end ---@param buffer integer ----@param item markview.parsed.doctext.issues -doctext.issue = function (buffer, item) +---@param item markview.parsed.comment.issues +comment.issue = function (buffer, item) ---|fS - ---@type markview.config.doctext.tasks? - local main_config = spec.get({ "doctext", "issues" }, { fallback = nil }); + ---@type markview.config.comment.tasks? + local main_config = spec.get({ "comment", "issues" }, { fallback = nil }); if not main_config then return; end - ---@type markview.config.doctext.tasks.opts? + ---@type markview.config.comment.tasks.opts? local config = utils.match(main_config, item.text[1] or "", { ignore_keys = { "enable" }, eval_args = { buffer, item } @@ -104,7 +104,7 @@ doctext.issue = function (buffer, item) local range = item.range; - vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.row_start, range.col_start, { + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { undo_restore = false, invalidate = true, virt_text_pos = "inline", @@ -118,7 +118,7 @@ doctext.issue = function (buffer, item) hl_mode = "combine" }); - vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.row_start, range.col_start, { + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { undo_restore = false, invalidate = true, end_row = range.row_end, end_col = range.col_end, @@ -126,7 +126,7 @@ doctext.issue = function (buffer, item) hl_group = utils.set_hl(config.hl) }); - vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.row_end, range.col_end, { + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end, { undo_restore = false, invalidate = true, virt_text_pos = "inline", @@ -142,18 +142,18 @@ doctext.issue = function (buffer, item) end ---@param buffer integer ----@param item markview.parsed.doctext.mentions -doctext.mention = function (buffer, item) +---@param item markview.parsed.comment.mentions +comment.mention = function (buffer, item) ---|fS - ---@type markview.config.doctext.tasks? - local main_config = spec.get({ "doctext", "mentions" }, { fallback = nil }); + ---@type markview.config.comment.tasks? + local main_config = spec.get({ "comment", "mentions" }, { fallback = nil }); if not main_config then return; end - ---@type markview.config.doctext.tasks.opts? + ---@type markview.config.comment.tasks.opts? local config = utils.match(main_config, item.text[1] or "", { ignore_keys = { "enable" }, eval_args = { buffer, item } @@ -165,7 +165,7 @@ doctext.mention = function (buffer, item) local range = item.range; - vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.row_start, range.col_start, { + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { undo_restore = false, invalidate = true, end_col = range.col_start + 1, conceal = "", @@ -181,7 +181,7 @@ doctext.mention = function (buffer, item) hl_mode = "combine" }); - vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.row_start, range.col_start, { + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { undo_restore = false, invalidate = true, end_row = range.row_end, end_col = range.col_end, @@ -189,7 +189,7 @@ doctext.mention = function (buffer, item) hl_group = utils.set_hl(config.hl) }); - vim.api.nvim_buf_set_extmark(buffer, doctext.ns, range.row_end, range.col_end, { + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end, { undo_restore = false, invalidate = true, virt_text_pos = "inline", @@ -204,26 +204,81 @@ doctext.mention = function (buffer, item) ---|fE end +---@param buffer integer +---@param item markview.parsed.comment.inline_codes +comment.inline_code = function (buffer, item) + ---|fS + + ---@type markview.config.comment.inline_codes? + local config = spec.get({ "comment", "inline_codes" }, { fallback = nil }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_col = range.col_start + 1, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end - 1, { + undo_restore = false, invalidate = true, + end_col = range.col_end, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + --- Renders HTML elements ---@param buffer integer ----@param content markview.parsed.doctext[] -doctext.render = function (buffer, content) +---@param content markview.parsed.comment[] +comment.render = function (buffer, content) local custom = spec.get({ "renderers" }, { fallback = {} }); for _, item in ipairs(content or {}) do local success, err; if custom[item.class] then - success, err = pcall(custom[item.class], doctext.ns, buffer, item); + success, err = pcall(custom[item.class], comment.ns, buffer, item); else - success, err = pcall(doctext[item.class:gsub("^doctext_", "")], buffer, item); + success, err = pcall(comment[item.class:gsub("^comment_", "")], buffer, item); end if success == false then require("markview.health").print({ kind = "ERR", - from = "renderers/doctext.lua", + from = "renderers/comment.lua", fn = "render() -> " .. item.class, message = { @@ -238,8 +293,8 @@ end ---@param buffer integer ---@param from integer ---@param to integer -doctext.clear = function (buffer, from, to) - vim.api.nvim_buf_clear_namespace(buffer, doctext.ns, from or 0, to or -1); +comment.clear = function (buffer, from, to) + vim.api.nvim_buf_clear_namespace(buffer, comment.ns, from or 0, to or -1); end -return doctext; +return comment; diff --git a/lua/markview/spec.lua b/lua/markview/spec.lua index e68ae22..e8ef459 100644 --- a/lua/markview/spec.lua +++ b/lua/markview/spec.lua @@ -210,7 +210,7 @@ spec.default = { ---@type string[] Properties that should be sourced *externally*. spec.__external_config = { - "doctext", + "comment", "html", "markdown", "markdown_inline", diff --git a/lua/markview/types/parsers/doctext.lua b/lua/markview/types/parsers/comment.lua similarity index 60% rename from lua/markview/types/parsers/doctext.lua rename to lua/markview/types/parsers/comment.lua index 89bfd03..e9c1aac 100644 --- a/lua/markview/types/parsers/doctext.lua +++ b/lua/markview/types/parsers/comment.lua @@ -3,16 +3,16 @@ ------------------------------------------------------------------------------ --- A `task`. ----@class markview.parsed.doctext.tasks +---@class markview.parsed.comment.tasks --- ----@field class "doctext_task" +---@field class "comment_task" --- ---@field kind string Type of task(e.g. `feat`, `TODO` etc.) ---@field text string ----@field range markview.parsed.doctext.tasks.range +---@field range markview.parsed.comment.tasks.range ----@class markview.parsed.doctext.tasks.range +---@class markview.parsed.comment.tasks.range --- ---@field label_row_end? integer End row of a label(A label may be like `foo:`, `bar(topic):`). ---@field label_col_end? integer End column of a label(A label may be like `foo:`, `bar(topic):`). @@ -26,23 +26,32 @@ --- An issue reference. ----@class markview.parsed.doctext.issues +---@class markview.parsed.comment.issues --- ----@field class "doctext_issue" +---@field class "comment_issue" --- ---@field text string ---@field range markview.parsed.range --- A mention. ----@class markview.parsed.doctext.mentions +---@class markview.parsed.comment.mentions --- ----@field class "doctext_mention" +---@field class "comment_mention" +--- +---@field text string +---@field range markview.parsed.range + + +--- A mention. +---@class markview.parsed.comment.inline_codes +--- +---@field class "comment_inline_code" --- ---@field text string ---@field range markview.parsed.range ------------------------------------------------------------------------------ ----@alias markview.parsed.doctext ----| markview.parsed.doctext.tasks +---@alias markview.parsed.comment +---| markview.parsed.comment.tasks diff --git a/lua/markview/types/renderers/comment.lua b/lua/markview/types/renderers/comment.lua new file mode 100644 index 0000000..6701575 --- /dev/null +++ b/lua/markview/types/renderers/comment.lua @@ -0,0 +1,35 @@ +---@meta + +------------------------------------------------------------------------------ + +---@class markview.config.comment.tasks +--- +---@field enable boolean +--- +---@field default markview.config.comment.tasks.opts +---@field [string] markview.config.comment.tasks.opts + + +---@class markview.config.comment.tasks.opts markview.config.__inline +--- +---@field corner_left? string Left corner. +---@field corner_left_hl? string Highlight group for the left corner. +--- +---@field padding_left? string Left padding(added after `corner_left`). +---@field padding_left_hl? string Highlight group for the left padding. +--- +---@field icon? string Icon(added after `padding_left`). +---@field icon_hl? string Highlight group for the icon. +--- +---@field hl? string Default highlight group(used by `*_hl` options when they are not set). +---@field desc_hl? string Highlight group for the `description`. +--- +---@field padding_right? string Right padding. +---@field padding_right_hl? string Highlight group for the right padding. +--- +---@field corner_right? string Right corner(added after `padding_right`). +---@field corner_right_hl? string Highlight group for the right corner. + +------------------------------------------------------------------------------ + +---@alias markview.config.comment.inline_codes markview.config.__inline diff --git a/lua/markview/types/renderers/doctext.lua b/lua/markview/types/renderers/doctext.lua deleted file mode 100644 index aab7896..0000000 --- a/lua/markview/types/renderers/doctext.lua +++ /dev/null @@ -1,13 +0,0 @@ ----@meta - ------------------------------------------------------------------------------- - ----@class markview.config.doctext.tasks ---- ----@field enable boolean ---- ----@field default markview.config.doctext.tasks.opts ----@field [string] markview.config.doctext.tasks.opts - - ----@alias markview.config.doctext.tasks.opts markview.config.__inline From 06fa1fc145e4f3b252c3f75603f842ccc98bc36d Mon Sep 17 00:00:00 2001 From: Shawon Date: Fri, 2 Jan 2026 10:07:20 +0600 Subject: [PATCH 07/31] feat(comment): Added `code_block` support --- lua/markview/config/comment.lua | 35 ++ lua/markview/parsers/comment.lua | 42 ++- lua/markview/renderer.lua | 1 + lua/markview/renderers/comment.lua | 390 +++++++++++++++++++++++ lua/markview/types/parsers/comment.lua | 37 +++ lua/markview/types/renderers/comment.lua | 60 ++++ 6 files changed, 562 insertions(+), 3 deletions(-) diff --git a/lua/markview/config/comment.lua b/lua/markview/config/comment.lua index 40a9818..c13d538 100644 --- a/lua/markview/config/comment.lua +++ b/lua/markview/config/comment.lua @@ -1,6 +1,41 @@ return { enable = true, + code_blocks = { + enable = true, + + border_hl = "MarkviewCode", + info_hl = "MarkviewCodeInfo", + + label_direction = "right", + label_hl = nil, + + min_width = 60, + pad_amount = 2, + pad_char = " ", + + default = { + block_hl = "MarkviewCode", + pad_hl = "MarkviewCode" + }, + + ["diff"] = { + block_hl = function (_, line) + if line:match("^%+") then + return "MarkviewPalette4"; + elseif line:match("^%-") then + return "MarkviewPalette1"; + else + return "MarkviewCode"; + end + end, + pad_hl = "MarkviewCode" + }, + + style = "block", + sign = true, + }, + inline_codes = { padding_left = " ", padding_right = " ", diff --git a/lua/markview/parsers/comment.lua b/lua/markview/parsers/comment.lua index e875161..db8c208 100644 --- a/lua/markview/parsers/comment.lua +++ b/lua/markview/parsers/comment.lua @@ -74,22 +74,58 @@ comment.inline_code = function (_, _, text, range) }); end ---- Issue. +-- Issue. ---@param buffer integer ---@param TSNode TSNode ---@param text string[] ----@param range markview.parsed.range +---@param range markview.parsed.comment.code_blocks.range comment.code_block = function (buffer, TSNode, text, range) - local lang = TSNode:field("type")[1]; + local uses_tab = false; + + local lang = TSNode:field("language")[1]; local language; if lang then language = vim.treesitter.get_node_text(lang, buffer, {}); + range.language = { lang:range() }; + end + + for _, line in ipairs(text) do + if string.match(line, "\t") then + uses_tab = true; + break; + end + end + + ---@type TSNode, TSNode? + local start_delim, end_delim; + + for child in TSNode:iter_children() do + if child:type() == "start_delimiter" then + start_delim = child; + local delim = vim.treesitter.get_node_text(child, buffer, {}); + + range.start_delim = { child:range() }; + range.start_delim[2] = range.start_delim[2] + #string.match(delim, "^%s*"); + elseif child:type() == "end_delimiter" then + end_delim = child; + local delim = vim.treesitter.get_node_text(child, buffer, {}); + + range.end_delim = { child:range() }; + range.end_delim[2] = range.end_delim[2] + #string.match(delim, "^%s*"); + end end comment.insert({ class = "comment_code_block", + uses_tab = uses_tab, + language = language, + info_string = nil, + delimiters = { + start_delim and vim.treesitter.get_node_text(start_delim, buffer) or "", + end_delim and vim.treesitter.get_node_text(end_delim, buffer) or "", + }, text = text, range = range, diff --git a/lua/markview/renderer.lua b/lua/markview/renderer.lua index 2e7a332..8bbe4b2 100644 --- a/lua/markview/renderer.lua +++ b/lua/markview/renderer.lua @@ -463,6 +463,7 @@ renderer.clear = function (buffer, from, to, hybrid_mode) ---|fS local _renderers = { + comment = require("markview.renderers.comment"); html = require("markview.renderers.html"); markdown = require("markview.renderers.markdown"); markdown_inline = require("markview.renderers.markdown_inline"); diff --git a/lua/markview/renderers/comment.lua b/lua/markview/renderers/comment.lua index 9e627ee..834a340 100644 --- a/lua/markview/renderers/comment.lua +++ b/lua/markview/renderers/comment.lua @@ -80,6 +80,67 @@ comment.task = function (buffer, item) ---|fE end +---@param buffer integer +---@param item markview.parsed.comment.issues +comment.task_scope = function (buffer, item) + ---|fS + + ---@type markview.config.comment.tasks? + local main_config = spec.get({ "comment", "task_scopes" }, { fallback = nil }); + + if not main_config then + return; + end + + ---@type markview.config.comment.tasks.opts? + local config = utils.match(main_config, item.text[1] or "", { + ignore_keys = { "enable" }, + eval_args = { buffer, item } + }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + ---@param buffer integer ---@param item markview.parsed.comment.issues comment.issue = function (buffer, item) @@ -259,6 +320,335 @@ comment.inline_code = function (buffer, item) ---|fE end +--- Renders fenced code blocks. +---@param buffer integer +---@param item markview.parsed.comment.code_blocks +comment.code_block = function (buffer, item) + ---|fS + + ---@type markview.config.comment.code_blocks? + local config = spec.get({ "comment", "code_blocks" }, { fallback = nil, eval_args = { buffer, item } }); + + local delims = item.delimiters; + local range = item.range; + + local info_range = range.info_string or {}; + + if not config then + return; + end + + -- vim.print(item) + + local decorations = require("markview.filetypes").get(item.language); + local label = { string.format(" %s%s ", decorations.icon, decorations.name), config.label_hl or decorations.icon_hl }; + local win = utils.buf_getwin(buffer); + + --- Column end for concealing code block language string. + ---@return integer + local function lang_conceal_to () + if item.info_string == nil then + return range.start_delim[4]; + else + local _to = item.info_string:match("^%S+%s*"):len(); + return (range.info_string and range.info_string[2] or range.start_delim[4]) + _to; + end + end + + --- Gets highlight configuration for a line. + ---@param line string + ---@return markview.config.comment.code_blocks.opts + local function get_line_config(line) + local line_conf = utils.match(config, item.language, { + eval_args = { buffer, line }, + def_fallback = { + block_hl = config.border_hl, + pad_hl = config.border_hl + }, + fallback = { + block_hl = config.border_hl, + pad_hl = config.border_hl + } + }); + + return line_conf; + end + + --[[ *Basic* rendering of `code blocks`. ]] + local function render_simple() + ---|fS + + ---@cast config markview.config.comment.code_blocks.simple + + local conceal_from = range.start_delim[2]; + local conceal_to = range.col_start + #(item.text[1] or ""); + + if config.label_direction == nil or config.label_direction == "left" then + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, conceal_from, { + undo_restore = false, invalidate = true, + + end_col = conceal_to, + conceal = "", + + sign_text = config.sign == true and decorations.sign or nil, + sign_hl_group = utils.set_hl(config.sign_hl or decorations.sign_hl), + + virt_text_pos = "inline", + virt_text = { label }, + + line_hl_group = utils.set_hl(config.border_hl) + }); + else + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, conceal_from, { + undo_restore = false, invalidate = true, + + end_col = conceal_to, + conceal = "", + + sign_text = config.sign == true and decorations.sign or nil, + sign_hl_group = utils.set_hl(config.sign_hl or decorations.sign_hl), + + virt_text_pos = "right_align", + virt_text = { label }, + + line_hl_group = utils.set_hl(config.border_hl) + }); + end + + --- Background + for l = range.row_start + 1, range.row_end - 1 do + local line = item.text[(l - range.row_start) + 1]; + local line_config = get_line_config(line); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, l, 0, { + undo_restore = false, invalidate = true, + end_row = l, + + line_hl_group = utils.set_hl(line_config.block_hl --[[ @as string ]]) + }); + end + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, (range.col_start + #item.text[#item.text]) - #delims[2], { + undo_restore = false, invalidate = true, + end_col = range.col_start + #item.text[#item.text], + conceal = "", + + line_hl_group = utils.set_hl(config.border_hl) + }); + + ---|fE + end + + --- Renders block style code blocks. + local function render_block () + ---|fS + + ---@cast config markview.config.comment.code_blocks.block + + ---|fS "chunk: Calculate various widths" + + local pad_amount = config.pad_amount or 0; + local block_width = config.min_width or 60; + + local pad_char = config.pad_char or " "; + + ---@type integer[] Visual width of lines. + local line_widths = {}; + + for l, line in ipairs(item.text) do + local final = require("markview.renderers.markdown").get_visual_text:init(decorations.name, line); + + if l ~= 1 and l ~= #item.text then + table.insert(line_widths, vim.fn.strdisplaywidth(final)); + + if vim.fn.strdisplaywidth(final) > (block_width - (2 * pad_amount)) then + block_width = vim.fn.strdisplaywidth(final) + (2 * pad_amount); + end + end + end + + local label_width = utils.virt_len({ label }); + + ---|fE + + local delim_conceal_from = range.start_delim[2]; + local conceal_to = range.col_start + #(item.text[1] or ""); + + ---|fS "chunk: Top border" + + local left_padding = pad_amount; + + local pad_width = vim.fn.strdisplaywidth( + string.rep(pad_char, left_padding) + ); + + -- Hide the leading `backticks`s. + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + + end_col = conceal_to, + conceal = "" + }); + + if config.label_direction == "right" then + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, delim_conceal_from, { + virt_text_pos = "inline", + virt_text = { + { + string.rep(" " or pad_char, left_padding), + utils.set_hl(config.border_hl) + } + } + }); + else + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start + #item.text[1], { + virt_text_pos = "inline", + virt_text = { + { + string.rep(" " or pad_char, left_padding), + utils.set_hl(config.border_hl) + } + } + }); + end + + -- Calculating the amount of spacing to add, + -- 1. Used space = label width(`label_width`) + padding size(`pad_width`). + -- 2. Total block width - Used space + local spacing = block_width - (label_width + pad_width); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start + #item.text[1], { + virt_text_pos = "inline", + virt_text = { + { + string.rep(pad_char, spacing), + utils.set_hl(config.border_hl) + }, + } + }); + + ---|fS "chunk: Place label" + + local top_border = { + }; + + if config.label_direction == "right" then + top_border.col_start = range.start_delim[2] + #item.text[1]; + else + top_border.col_start = range.start_delim[4]; + end + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, top_border.col_start, { + virt_text_pos = "inline", + virt_text = { label } + }); + + ---|fE + + ---|fE + + --- Line padding + for l, width in ipairs(line_widths) do + local line = item.text[l + 1]; + local line_config = get_line_config(line); + + if width ~= 0 then + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start + l, line ~= "" and range.col_start or 0, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { + string.rep(" ", pad_amount), + utils.set_hl(line_config.pad_hl --[[ @as string ]]) + } + }, + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start + l, range.col_start + #line, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { + string.rep(" ", math.max(0, block_width - (( 2 * pad_amount) + width))), + utils.set_hl(line_config.block_hl --[[ @as string ]]) + }, + { + string.rep(" ", pad_amount), + utils.set_hl(line_config.pad_hl --[[ @as string ]]) + } + }, + }); + + --- Background + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start + l, range.col_start, { + undo_restore = false, invalidate = true, + end_col = range.col_start + #line, + + hl_group = utils.set_hl(line_config.block_hl --[[ @as string ]]) + }); + else + local buf_line = vim.api.nvim_buf_get_lines(buffer, range.row_start + l, range.row_start + l + 1, false)[1]; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start + l, #buf_line, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { + string.rep(" ", math.max(0, range.col_start - #buf_line)) + }, + { + string.rep(" ", pad_amount), + utils.set_hl(line_config.pad_hl --[[ @as string ]]) + }, + { + string.rep(" ", math.max(0, block_width - (2 * pad_amount))), + utils.set_hl(line_config.block_hl --[[ @as string ]]) + }, + { + string.rep(" ", pad_amount), + utils.set_hl(line_config.pad_hl --[[ @as string ]]) + }, + }, + }); + end + end + + --- Render bottom + local end_delim_conceal_from = range.end_delim[2] + #string.match(item.delimiters[2], "^%s*"); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, end_delim_conceal_from, { + undo_restore = false, invalidate = true, + end_col = range.col_start + #item.text[#item.text], + conceal = "" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, end_delim_conceal_from, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { + string.rep(" ", block_width), + utils.set_hl(config.border_hl) + } + } + }); + + ---|fE + end + + if not win or config.style == "simple" or item.uses_tab or ( vim.o.wrap == true or vim.wo[win].wrap == true ) then + render_simple(); + elseif config.style == "block" then + render_block() + end + + ---|fE +end + --- Renders HTML elements ---@param buffer integer ---@param content markview.parsed.comment[] diff --git a/lua/markview/types/parsers/comment.lua b/lua/markview/types/parsers/comment.lua index e9c1aac..1089679 100644 --- a/lua/markview/types/parsers/comment.lua +++ b/lua/markview/types/parsers/comment.lua @@ -24,6 +24,7 @@ ---@field col_start integer ---@field col_end integer +------------------------------------------------------------------------------ --- An issue reference. ---@class markview.parsed.comment.issues @@ -33,6 +34,7 @@ ---@field text string ---@field range markview.parsed.range +------------------------------------------------------------------------------ --- A mention. ---@class markview.parsed.comment.mentions @@ -42,6 +44,7 @@ ---@field text string ---@field range markview.parsed.range +------------------------------------------------------------------------------ --- A mention. ---@class markview.parsed.comment.inline_codes @@ -53,5 +56,39 @@ ------------------------------------------------------------------------------ +---@class markview.parsed.comment.code_blocks +--- +---@field class "markdown_code_block" +---@field uses_tab boolean Does the code block use tab inside it? Used for switching render style. +--- +---@field delimiters [ string, string ] Code block delimiters(```). +---@field language string? Language string(typically after ```). +---@field info_string string? Extra information(typically after the language). +--- +---@field text string[] +---@field range markview.parsed.comment.code_blocks.range + + +---@class markview.parsed.comment.code_blocks.range +--- +---@field start_delim integer[] Range of the **start** delimiter. +---@field end_delim? integer[] Range of the **end** delimiter. +--- +---@field row_start integer +---@field row_end integer +---@field col_start integer +---@field col_end integer +--- +---@field language? integer[] Range of the language string. +---@field info_string? integer[] Range of info string. + +------------------------------------------------------------------------------ + ---@alias markview.parsed.comment ---| markview.parsed.comment.tasks + + +---@class markview.parsed.comment_sorted +--- +---@field tasks markview.parsed.comment.tasks[] + diff --git a/lua/markview/types/renderers/comment.lua b/lua/markview/types/renderers/comment.lua index 6701575..0fe846d 100644 --- a/lua/markview/types/renderers/comment.lua +++ b/lua/markview/types/renderers/comment.lua @@ -33,3 +33,63 @@ ------------------------------------------------------------------------------ ---@alias markview.config.comment.inline_codes markview.config.__inline + +------------------------------------------------------------------------------ + +--- Configuration for code blocks. +---@alias markview.config.comment.code_blocks +---| markview.config.comment.code_blocks.simple +---| markview.config.comment.code_blocks.block + + +---@class markview.config.comment.code_blocks.simple +--- +---@field enable boolean Enable rendering of code blocks. +--- +---@field border_hl? string Highlight group for borders. +---@field info_hl? string Highlight group for the info string. +--- +---@field label_direction? "left" | "right" Position of the language & icon. +---@field label_hl? string Highlight group for the label. +--- +---@field sign? boolean Enables signs for the code block? +---@field sign_hl? string Highlight group for the sign. +--- +---@field style "simple" Only highlights the line. Enabled when `wrap` is enabled. +--- +---@field default markview.config.comment.code_blocks.opts +---@field [string] markview.config.comment.code_blocks.opts + + +---@class markview.config.comment.code_blocks.block +--- +---@field enable boolean Enable rendering of code blocks. +--- +---@field border_hl? string Highlight group for borders. +---@field info_hl? string Highlight group for the info string. +--- +---@field label_direction? "left" | "right" Position of the language & icon. +---@field label_hl? string Highlight group for the label. +--- +---@field min_width? integer Minimum width of the code block. +---@field pad_amount? integer Number of `pad_char`s to add on the left & right side of the code block. +---@field pad_char? string Character used as padding. +--- +---@field sign? boolean Enables signs for the code block? +---@field sign_hl? string Highlight group for the sign. +--- +---@field style "block" Creates a block around the code block. Disabled when `wrap` is enabled. +--- +---@field default markview.config.comment.code_blocks.opts +---@field [string] markview.config.comment.code_blocks.opts + + +--[[ Configuration for highlighting `lines` inside a code block. ]] +---@class markview.config.comment.code_blocks.opts +--- +---@field block_hl +---| string Highlight group for the background of the line. +---| fun(buffer: integer, line: string): string? Takes `line` & the `buffer` containing it and returns a highlight group for the line. +---@field pad_hl +---| string Highlight group for the padding of the line. +---| fun(buffer: integer, line: string): string? Takes `line` & the `buffer` containing it and returns a highlight group for the padding.. From 6da007d6cffa72de7c10fe04ab05b0bfb35e4509 Mon Sep 17 00:00:00 2001 From: Shawon Date: Fri, 2 Jan 2026 10:47:54 +0600 Subject: [PATCH 08/31] feat(comment): Added `url`, `taglink` & `autolink` --- lua/markview/parsers/comment.lua | 2 +- lua/markview/renderers/comment.lua | 191 +++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+), 1 deletion(-) diff --git a/lua/markview/parsers/comment.lua b/lua/markview/parsers/comment.lua index db8c208..3fa8cc9 100644 --- a/lua/markview/parsers/comment.lua +++ b/lua/markview/parsers/comment.lua @@ -192,7 +192,7 @@ comment.taglink = function (_, _, text, range) }); end ---- HTML parser +--- Comment parser ---@param buffer integer ---@param TSTree table ---@param from integer? diff --git a/lua/markview/renderers/comment.lua b/lua/markview/renderers/comment.lua index 834a340..7e78d4b 100644 --- a/lua/markview/renderers/comment.lua +++ b/lua/markview/renderers/comment.lua @@ -649,6 +649,197 @@ comment.code_block = function (buffer, item) ---|fE end +---@param buffer integer +---@param item markview.parsed.comment.urls +comment.url = function (buffer, item) + ---|fS + + ---@type markview.config.comment.urls? + local main_config = spec.get({ "comment", "urls" }, { fallback = nil }); + + if not main_config then + return; + end + + ---@type markview.config.comment.urls.opts? + local config = utils.match(main_config, item.text[1] or "", { + ignore_keys = { "enable" }, + eval_args = { buffer, item } + }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + +---@param buffer integer +---@param item markview.parsed.comment.taglinks +comment.taglink = function (buffer, item) + ---|fS + + ---@type markview.config.comment.taglinks? + local main_config = spec.get({ "comment", "taglinks" }, { fallback = nil }); + + if not main_config then + return; + end + + ---@type markview.config.comment.taglinks.opts? + local config = utils.match(main_config, item.text[1] or "", { + ignore_keys = { "enable" }, + eval_args = { buffer, item } + }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_col = range.col_start + 1, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end - 1, { + undo_restore = false, invalidate = true, + end_col = range.col_end, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + +---@param buffer integer +---@param item markview.parsed.comment.autolinks +comment.autolink = function (buffer, item) + ---|fS + + ---@type markview.config.comment.autolinks? + local main_config = spec.get({ "comment", "autolinks" }, { fallback = nil }); + + if not main_config then + return; + end + + ---@type markview.config.comment.autolinks.opts? + local config = utils.match(main_config, item.text[1] or "", { + ignore_keys = { "enable" }, + eval_args = { buffer, item } + }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_col = range.col_start + 1, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end - 1, { + undo_restore = false, invalidate = true, + end_col = range.col_end, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + --- Renders HTML elements ---@param buffer integer ---@param content markview.parsed.comment[] From c99341c143a22579605e3dafeff2e821d1f75a44 Mon Sep 17 00:00:00 2001 From: Shawon Date: Thu, 8 Jan 2026 21:49:43 +0600 Subject: [PATCH 09/31] fix(filetypes): Proerly handle `nil` values Return `"Unknown"` instead of `""`. --- lua/markview/filetypes.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/markview/filetypes.lua b/lua/markview/filetypes.lua index 34115c5..41e4baa 100644 --- a/lua/markview/filetypes.lua +++ b/lua/markview/filetypes.lua @@ -781,7 +781,7 @@ fts.get = function (ft) end local this_conf = fts.styles[_ft] or fts.styles[ft] or fts.styles.default; - conf.name = this_conf.name or string.gsub(ft, "^%w", string.upper) or "Unknown"; + conf.name = this_conf.name or ( type(ft) == "string" and string.gsub(ft, "^%w", string.upper) or "Unknown" ); return conf; end From f83c081895c8fa06c162b431146781fc187bcc28 Mon Sep 17 00:00:00 2001 From: Shawon Date: Thu, 8 Jan 2026 21:52:27 +0600 Subject: [PATCH 10/31] feat(comment): Added option for rendering *fancy comments* --- lua/markview/autocmds.lua | 25 +++++++++++++++++++------ lua/markview/spec.lua | 19 ++++++++++++++++++- lua/markview/types/experimental.lua | 2 ++ lua/markview/types/preview.lua | 2 +- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/lua/markview/autocmds.lua b/lua/markview/autocmds.lua index c5f5494..cbb5976 100644 --- a/lua/markview/autocmds.lua +++ b/lua/markview/autocmds.lua @@ -183,13 +183,26 @@ autocmds.bufHandle = function (args) local condition = spec.get({ "preview", "condition" }, { eval_args = { args.buf }, ignore_enable = true }); - if vim.list_contains(ignore_bt, bt) == true then - --- Ignored buffer type. - return; - elseif vim.list_contains(attach_ft, ft) == false then - --- Ignored file type. - return; + --[[ + feat: Attaching to buffers. + + If condition is `true`(either `preview.condition = true` or the evaluated function value is `true`), attach to `buffer`. + + Otherwise, check if the **buftype** is included in `preview.ignore_buftypes`. If it is then we don't attach to `buffer`. + Then check if the **filetype** is included in `preview.filetypes`. IF it is we attach to `buffer`. + ]] + if condition == nil then + -- No condition specified. + + if vim.list_contains(ignore_bt, bt) == true then + --- Ignored buffer type. + return; + elseif vim.list_contains(attach_ft, ft) == false then + --- Ignored file type. + return; + end elseif condition == false then + -- Condition not met. return; end diff --git a/lua/markview/spec.lua b/lua/markview/spec.lua index e8ef459..d35690f 100644 --- a/lua/markview/spec.lua +++ b/lua/markview/spec.lua @@ -8,6 +8,8 @@ local spec = {}; ---@type markview.config spec.default = { experimental = { + fancy_comments = false, + date_formats = { "^%d%d%d%d%-%d%d%-%d%d$", --- YYYY-MM-DD "^%d%d%-%d%d%-%d%d%d%d$", --- DD-MM-YYYY, MM-DD-YYYY @@ -187,8 +189,23 @@ spec.default = { debounce = 150, icon_provider = "internal", - filetypes = { "markdown", "quarto", "rmd", "typst", "doctext", }, + filetypes = { "markdown", "quarto", "rmd", "typst", }, ignore_buftypes = { "nofile" }, + condition = function (buffer) + local is_enabled = spec.get({ "experimental", "fancy_comments" }, { + fallback = false, + }); + + if not is_enabled then + return false; + end + + local success, parser = pcall(vim.treesitter.get_parser, buffer); + if success and parser ~= nil then + return true; + end + end, + raw_previews = {}, modes = { "n", "no", "c" }, diff --git a/lua/markview/types/experimental.lua b/lua/markview/types/experimental.lua index c693694..ac3356a 100644 --- a/lua/markview/types/experimental.lua +++ b/lua/markview/types/experimental.lua @@ -3,6 +3,8 @@ --- Experimental options. ---@class markview.config.experimental --- +---@field fancy_comments boolean When `true`, enables preview on **all buffers** with an active `tree-sitter parser`. +--- ---@field date_formats string[] List of lua patterns for detecting date in YAML. ---@field date_time_formats string[] List of lua patterns for detecting date & time in YAML. --- diff --git a/lua/markview/types/preview.lua b/lua/markview/types/preview.lua index 9f4888a..8c77511 100644 --- a/lua/markview/types/preview.lua +++ b/lua/markview/types/preview.lua @@ -22,7 +22,7 @@ ---@field ignore_buftypes? string[] Buftypes that should be ignored(e.g. nofile). ---@field raw_previews? markview.config.preview.raw Options that will show up as raw in hybrid mode. --- ----@field condition? fun(buffer: integer): boolean Condition to check if a buffer should be attached or not. +---@field condition? fun(buffer: integer): boolean? Condition to check if a buffer should be attached or not. Overrides `preview.filetypes` & `preview.ignore_buftypes`. If `nil` is returned, `preview.filetypes` & `preview.ignore_buftypes` are checked. --- ---@field modes? string[] Vim-modes where previews will be shown. ---@field hybrid_modes? string[] Vim-modes where `hybrid mode` is enabled. Options that should/shouldn't be previewed in `hybrid_modes`. From 124b1a340a79fa7b571195951fbbf231ba4f815e Mon Sep 17 00:00:00 2001 From: Shawon Date: Thu, 8 Jan 2026 23:19:20 +0600 Subject: [PATCH 11/31] doc(comment): Added some type defs --- lua/markview/types/parsers/comment.lua | 30 +++++++++++++++ lua/markview/types/renderers/comment.lua | 49 ++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/lua/markview/types/parsers/comment.lua b/lua/markview/types/parsers/comment.lua index 1089679..89756e5 100644 --- a/lua/markview/types/parsers/comment.lua +++ b/lua/markview/types/parsers/comment.lua @@ -36,6 +36,36 @@ ------------------------------------------------------------------------------ +--- An URL. +---@class markview.parsed.comment.urls +--- +---@field class "comment_url" +--- +---@field text string +---@field range markview.parsed.range + +------------------------------------------------------------------------------ + +--- An taglink. +---@class markview.parsed.comment.autolinks +--- +---@field class "comment_autolink" +--- +---@field text string +---@field range markview.parsed.range + +------------------------------------------------------------------------------ + +--- A taglink. +---@class markview.parsed.comment.taglinks +--- +---@field class "comment_taglink" +--- +---@field text string +---@field range markview.parsed.range + +------------------------------------------------------------------------------ + --- A mention. ---@class markview.parsed.comment.mentions --- diff --git a/lua/markview/types/renderers/comment.lua b/lua/markview/types/renderers/comment.lua index 0fe846d..002e860 100644 --- a/lua/markview/types/renderers/comment.lua +++ b/lua/markview/types/renderers/comment.lua @@ -2,6 +2,17 @@ ------------------------------------------------------------------------------ +--[[ Configuration for `comments`. ]] +---@class markview.config.comment +--- +---@field enable boolean Enable **comment** rendering. +--- +---@field code_blocks markview.config.comment.code_blocks +---@field inline_codes markview.config.comment.inline_codes +---@field tasks markview.config.comment.tasks + +------------------------------------------------------------------------------ + ---@class markview.config.comment.tasks --- ---@field enable boolean @@ -93,3 +104,41 @@ ---@field pad_hl ---| string Highlight group for the padding of the line. ---| fun(buffer: integer, line: string): string? Takes `line` & the `buffer` containing it and returns a highlight group for the padding.. + +------------------------------------------------------------------------------ + +---@alias markview.config.comment.issues markview.config.__inline +---@alias markview.config.comment.mentions markview.config.__inline + +------------------------------------------------------------------------------ + +--- Configuration for block reference links. +---@class markview.config.comment.urls +--- +---@field enable boolean Enable rendering of `URL`s. +--- +---@field default markview.config.__inline Default configuration for URLs. +---@field [string] markview.config.__inline Configuration for URLs whose text matches with the key's pattern. + + +------------------------------------------------------------------------------ + +--- Configuration for block taglinks. +---@class markview.config.comment.taglinks +--- +---@field enable boolean Enable rendering of `URL`s. +--- +---@field default markview.config.__inline Default configuration. +---@field [string] markview.config.__inline Configuration for URLs matching the key's pattern. + +------------------------------------------------------------------------------ + +--- Configuration for block autolinks. +---@class markview.config.comment.autolinks +--- +---@field enable boolean Enable rendering of `URL`s. +--- +---@field default markview.config.__inline Default configuration. +---@field [string] markview.config.__inline Configuration for URLs matching the key's pattern. + + From 3d758ace0f7552a34ecc0162488d977598ed558d Mon Sep 17 00:00:00 2001 From: Shawon Date: Fri, 9 Jan 2026 00:52:24 +0600 Subject: [PATCH 12/31] chore: Removed dead code --- lua/markview/renderers/comment.lua | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/lua/markview/renderers/comment.lua b/lua/markview/renderers/comment.lua index 7e78d4b..0b82844 100644 --- a/lua/markview/renderers/comment.lua +++ b/lua/markview/renderers/comment.lua @@ -332,8 +332,6 @@ comment.code_block = function (buffer, item) local delims = item.delimiters; local range = item.range; - local info_range = range.info_string or {}; - if not config then return; end @@ -344,17 +342,6 @@ comment.code_block = function (buffer, item) local label = { string.format(" %s%s ", decorations.icon, decorations.name), config.label_hl or decorations.icon_hl }; local win = utils.buf_getwin(buffer); - --- Column end for concealing code block language string. - ---@return integer - local function lang_conceal_to () - if item.info_string == nil then - return range.start_delim[4]; - else - local _to = item.info_string:match("^%S+%s*"):len(); - return (range.info_string and range.info_string[2] or range.start_delim[4]) + _to; - end - end - --- Gets highlight configuration for a line. ---@param line string ---@return markview.config.comment.code_blocks.opts @@ -661,7 +648,7 @@ comment.url = function (buffer, item) return; end - ---@type markview.config.comment.urls.opts? + ---@type markview.config.__inline? local config = utils.match(main_config, item.text[1] or "", { ignore_keys = { "enable" }, eval_args = { buffer, item } @@ -722,7 +709,7 @@ comment.taglink = function (buffer, item) return; end - ---@type markview.config.comment.taglinks.opts? + ---@type markview.config.__inline? local config = utils.match(main_config, item.text[1] or "", { ignore_keys = { "enable" }, eval_args = { buffer, item } @@ -787,7 +774,7 @@ comment.autolink = function (buffer, item) return; end - ---@type markview.config.comment.autolinks.opts? + ---@type markview.config.__inline? local config = utils.match(main_config, item.text[1] or "", { ignore_keys = { "enable" }, eval_args = { buffer, item } From 063a0db47fcdcf9653ed2ef00bde89a828883fd5 Mon Sep 17 00:00:00 2001 From: Shawon Date: Fri, 9 Jan 2026 00:53:00 +0600 Subject: [PATCH 13/31] doc: Updated some docs --- doc/markview.nvim-experimental.txt | 2 + doc/markview.nvim-preview.txt | 70 +++++++++++++++++++++--------- markview.nvim.wiki | 2 +- 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/doc/markview.nvim-experimental.txt b/doc/markview.nvim-experimental.txt index bd87639..65a0e3f 100644 --- a/doc/markview.nvim-experimental.txt +++ b/doc/markview.nvim-experimental.txt @@ -4,6 +4,8 @@ --- Experimental options. ---@class markview.config.experimental --- + ---@field fancy_comments boolean When `true`, enables preview on **all buffers** with an active `tree-sitter parser`. + --- ---@field date_formats string[] List of lua patterns for detecting date in YAML. ---@field date_time_formats string[] List of lua patterns for detecting date & time in YAML. --- diff --git a/doc/markview.nvim-preview.txt b/doc/markview.nvim-preview.txt index ddfe0ba..a22a750 100644 --- a/doc/markview.nvim-preview.txt +++ b/doc/markview.nvim-preview.txt @@ -23,7 +23,7 @@ ---@field ignore_buftypes? string[] Buftypes that should be ignored(e.g. nofile). ---@field raw_previews? markview.config.preview.raw Options that will show up as raw in hybrid mode. --- - ---@field condition? fun(buffer: integer): boolean Condition to check if a buffer should be attached or not. + ---@field condition? fun(buffer: integer): boolean? Condition to check if a buffer should be attached or not. Overrides `preview.filetypes` & `preview.ignore_buftypes`. If `nil` is returned, `preview.filetypes` & `preview.ignore_buftypes` are checked. --- ---@field modes? string[] Vim-modes where previews will be shown. ---@field hybrid_modes? string[] Vim-modes where `hybrid mode` is enabled. Options that should/shouldn't be previewed in `hybrid_modes`. @@ -196,11 +196,36 @@ condition *markview.nvim-preview.condition* A function that returns a boolean indicating if a buffer should be attached to. +▋  Important +▋ This will disable filetypes {9} & ignore_buftypes {8}. + ▋ 󰋽 Note -▋ This is run after filetypes {9} & ignore_buftypes {8} is checked. +▋ The function may return `nil`. In which case, filetypes {11} & ignore_buftypes +▋ {10} will be checked. Useful if you need sophisticated logic for buffer attaching. +For example, this is the default value. It attaches to any buffer that has +`tree-sitter` parser available when experimental.fancy_comments {12} is set to +`true`. + +>lua + condition = function (buffer) + local is_enabled = spec.get({ "experimental", "fancy_comments" }, { + fallback = false, + }); + + if not is_enabled then + return false; + end + + local success, parser = pcall(vim.treesitter.get_parser, buffer); + if success and parser ~= nil then + return true; + end + end, +< + -------------------------------------------------------------------------------- modes *markview.nvim-preview.modes* @@ -220,7 +245,7 @@ hybrid_modes *markview.nvim-preview.hybrid_modes* Modes where `hybrid mode` will be shown. ▋  Important -▋ The mode must also be preset in modes {10} for this to take effect! +▋ The mode must also be preset in modes {13} for this to take effect! ╭──────────────────────┬──────────────────────╮ │ │ `hybrid_modes = {}` │ @@ -238,7 +263,7 @@ linewise_hybrid_mode *markview.nvim-preview.linewise_hybrid_mode* linewise_hybrid_mode = false, < -Enables `linewise` hybrid mode. edit_range {11} is used to control the number of +Enables `linewise` hybrid mode. edit_range {14} is used to control the number of lines to clear around each cursor. ╭──────────────────────┬──────────────────────╮ @@ -267,7 +292,7 @@ Maximum number of lines a buffer can have for it to be rendered completely. ▋ cause lag when opening the buffer. If the line count is larger than this value, the buffer will be partially drawn. -draw_range {12} is used to control the number of lines drawn around each cursor. +draw_range {15} is used to control the number of lines drawn around each cursor. -------------------------------------------------------------------------------- draw_range *markview.nvim-preview.draw_range* @@ -291,10 +316,10 @@ edit_range *markview.nvim-preview.edit_range* < Number of lines above & below each cursor that are considered being edited. Only -useful in hybrid_modes {13}. +useful in hybrid_modes {16}. ▋  Important -▋ When linewise_hybrid_mode {14} is `false`, a Node only needs to partially be +▋ When linewise_hybrid_mode {17} is `false`, a Node only needs to partially be ▋ within the range for it to be considered being edited. ▋ So, things such as List items, Block quotes etc. may clear more lines than the ▋ specified amount. @@ -317,20 +342,23 @@ Window options for the `splitview` window. Passed directly to `nvim_open_win()`. Links ~ -1: #-preview-options -2: ./Experimental.md#prefer_nvim -3: ./Experimental.md#file_open_command -4: ./Experimental.md#prefer_nvim -5: #ignore_buftypes -6: #ignore_buftypes -7: #hybrid_modes -8: #ignore_buftypes -9: #filetypes -10: #modes -11: #edit_range -12: #draw_range -13: #hybrid_modes -14: #linewise_hybrid_mode +1: `markview.nvim-preview` +2: `markview.nvim-experimental.prefer_nvim` +3: `markview.nvim-experimental.file_open_command` +4: `markview.nvim-experimental.prefer_nvim` +5: `markview.nvim-preview.ignore_buftypes` +6: `markview.nvim-preview.ignore_buftypes` +7: `markview.nvim-preview.modes` +8: `markview.nvim-preview.ignore_buftypes` +9: `markview.nvim-preview.filetypes` +10: `markview.nvim-preview.ignore_buftypes` +11: `markview.nvim-preview.filetypes` +12: `markview.nvim-experimental.fancy_comments` +13: `markview.nvim-preview.modes` +14: `markview.nvim-preview.edit_range` +15: `markview.nvim-preview.draw_range` +16: `markview.nvim-preview.modes` +17: `markview.nvim-preview.linewise_hybrid_mode` Images ~ diff --git a/markview.nvim.wiki b/markview.nvim.wiki index 2f6e9a4..df2d1c2 160000 --- a/markview.nvim.wiki +++ b/markview.nvim.wiki @@ -1 +1 @@ -Subproject commit 2f6e9a41e27163e59fba3513eafd9ec156d13d71 +Subproject commit df2d1c2f2e1820b5e8dd81e5360e3699a0c98581 From 184a43a34c239758a0c9d8e6bf34559be113c49e Mon Sep 17 00:00:00 2001 From: Shawon Date: Fri, 9 Jan 2026 12:40:04 +0600 Subject: [PATCH 14/31] doc(comment): Added types --- lua/markview/types/parsers/comment.lua | 40 ++++++++++++++++++------ lua/markview/types/renderers/comment.lua | 39 +++++++++++++++++------ 2 files changed, 59 insertions(+), 20 deletions(-) diff --git a/lua/markview/types/parsers/comment.lua b/lua/markview/types/parsers/comment.lua index 89756e5..1536a16 100644 --- a/lua/markview/types/parsers/comment.lua +++ b/lua/markview/types/parsers/comment.lua @@ -2,6 +2,22 @@ ------------------------------------------------------------------------------ +--[[ +An autolink. + +```comment + +``` +]] +---@class markview.parsed.comment.autolinks +--- +---@field class "comment_autolink" +--- +---@field text string +---@field range markview.parsed.range + +------------------------------------------------------------------------------ + --- A `task`. ---@class markview.parsed.comment.tasks --- @@ -46,16 +62,6 @@ ------------------------------------------------------------------------------ ---- An taglink. ----@class markview.parsed.comment.autolinks ---- ----@field class "comment_autolink" ---- ----@field text string ----@field range markview.parsed.range - ------------------------------------------------------------------------------- - --- A taglink. ---@class markview.parsed.comment.taglinks --- @@ -115,10 +121,24 @@ ------------------------------------------------------------------------------ ---@alias markview.parsed.comment +---| markview.parsed.comment.autolinks +---| markview.parsed.comment.code_blocks +---| markview.parsed.comment.inline_codes +---| markview.parsed.comment.issues +---| markview.parsed.comment.mentions +---| markview.parsed.comment.taglinks ---| markview.parsed.comment.tasks +---| markview.parsed.comment.urls ---@class markview.parsed.comment_sorted --- +---@field autolinks markview.parsed.comment.autolinks[] +---@field code_blocks markview.parsed.comment.code_blocks[] +---@field inline_codes markview.parsed.comment.inline_codes[] +---@field issues markview.parsed.comment.issues[] +---@field mentions markview.parsed.comment.mentions[] +---@field taglinks markview.parsed.comment.taglinks[] ---@field tasks markview.parsed.comment.tasks[] +---@field urls markview.parsed.comment.urls[] diff --git a/lua/markview/types/renderers/comment.lua b/lua/markview/types/renderers/comment.lua index 002e860..471671d 100644 --- a/lua/markview/types/renderers/comment.lua +++ b/lua/markview/types/renderers/comment.lua @@ -7,9 +7,14 @@ --- ---@field enable boolean Enable **comment** rendering. --- +---@field autolinks markview.config.comment.autolinks ---@field code_blocks markview.config.comment.code_blocks ---@field inline_codes markview.config.comment.inline_codes +---@field issues markview.config.comment.issues +---@field mentions markview.config.comment.mentions +---@field taglinks markview.config.comment.taglinks ---@field tasks markview.config.comment.tasks +---@field urls markview.config.comment.urls ------------------------------------------------------------------------------ @@ -107,12 +112,27 @@ ------------------------------------------------------------------------------ ----@alias markview.config.comment.issues markview.config.__inline ----@alias markview.config.comment.mentions markview.config.__inline +--- Configuration for issues. +---@class markview.config.comment.issues +--- +---@field enable boolean Enable rendering of `#issue`s. +--- +---@field default markview.config.__inline Default configuration for issues. +---@field [string] markview.config.__inline Configuration for issues whose text matches with the key's pattern. + +------------------------------------------------------------------------------ + +--- Configuration for mentions. +---@class markview.config.comment.mentions +--- +---@field enable boolean Enable rendering of `@mention`s. +--- +---@field default markview.config.__inline Default configuration for mentions. +---@field [string] markview.config.__inline Configuration for mentions whose text matches with the key's pattern. ------------------------------------------------------------------------------ ---- Configuration for block reference links. +--- Configuration for URLs. ---@class markview.config.comment.urls --- ---@field enable boolean Enable rendering of `URL`s. @@ -123,22 +143,21 @@ ------------------------------------------------------------------------------ ---- Configuration for block taglinks. +--- Configuration for taglinks. ---@class markview.config.comment.taglinks --- ----@field enable boolean Enable rendering of `URL`s. +---@field enable boolean Enable rendering of `|taglink|`s. --- ---@field default markview.config.__inline Default configuration. ----@field [string] markview.config.__inline Configuration for URLs matching the key's pattern. +---@field [string] markview.config.__inline Configuration for taglinks matching the key's pattern. ------------------------------------------------------------------------------ ---- Configuration for block autolinks. +--- Configuration for autolinks. ---@class markview.config.comment.autolinks --- ----@field enable boolean Enable rendering of `URL`s. +---@field enable boolean Enable rendering of ``s. --- ---@field default markview.config.__inline Default configuration. ----@field [string] markview.config.__inline Configuration for URLs matching the key's pattern. - +---@field [string] markview.config.__inline Configuration for autolinks matching the key's pattern. From 628b09a226dded05295c5fef92e2aa83830b1b85 Mon Sep 17 00:00:00 2001 From: Shawon Date: Fri, 9 Jan 2026 12:40:34 +0600 Subject: [PATCH 15/31] refactor(utils): Added `case-insensitive` match option --- lua/markview/renderers/comment.lua | 2 ++ lua/markview/utils.lua | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lua/markview/renderers/comment.lua b/lua/markview/renderers/comment.lua index 0b82844..170e285 100644 --- a/lua/markview/renderers/comment.lua +++ b/lua/markview/renderers/comment.lua @@ -19,6 +19,8 @@ comment.task = function (buffer, item) ---@type markview.config.comment.tasks.opts? local config = utils.match(main_config, item.kind, { + case_insensitive = true, + ignore_keys = { "enable" }, eval_args = { buffer, item } }); diff --git a/lua/markview/utils.lua b/lua/markview/utils.lua index 2acd916..50f5a65 100644 --- a/lua/markview/utils.lua +++ b/lua/markview/utils.lua @@ -287,11 +287,20 @@ utils.create_user_command_class = function (config) return class; end +---@class markview.utils.match.opts +--- +---@field case_insensitive? boolean +---@field def_fallback? any +---@field default? boolean +---@field eval_args any[] +---@field ignore_keys? any[] +---@field key_mod? string + --- Gets a config from a list of config tables. --- NOTE, {name} will be used to index the config. ---@param config table ---@param name string ----@param opts { key_mod: string?, default: boolean, def_fallback: any?, eval_args: any[], ignore_keys?: any[] } +---@param opts markview.utils.match.opts ---@return any utils.match = function (config, name, opts) config = config or {}; @@ -347,15 +356,22 @@ utils.match = function (config, name, opts) local function is_valid (value, pattern) local ignore = opts.ignore_keys or { "enable" }; + + local _value = value; local _pattern = pattern; if opts.key_mod then _pattern = string.format(opts.key_mod, _pattern); end + if opts.case_insensitive and type(_value) == "string" then + _value = string.lower(_value); + _pattern = string.lower(_pattern); + end + if vim.list_contains(ignore, pattern) then return false; - elseif string.match(value, _pattern) then + elseif string.match(_value, _pattern) then return true; else return false; From ab00aa4fb1270e55ecc18039a062c2ccd6d02d48 Mon Sep 17 00:00:00 2001 From: Shawon Date: Fri, 9 Jan 2026 12:41:42 +0600 Subject: [PATCH 16/31] feat(config, comment, tasks): Added more task type configs feat(config, comment): Added missing config options --- lua/markview/config/comment.lua | 210 +++++++++++++++++++++++++++++++- 1 file changed, 205 insertions(+), 5 deletions(-) diff --git a/lua/markview/config/comment.lua b/lua/markview/config/comment.lua index c13d538..2b6706b 100644 --- a/lua/markview/config/comment.lua +++ b/lua/markview/config/comment.lua @@ -1,6 +1,20 @@ +---@type markview.config.comment return { enable = true, + autolinks = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = "󰋽 ", + + hl = "MarkviewPalette6", + }, + }, + code_blocks = { enable = true, @@ -37,24 +51,41 @@ return { }, inline_codes = { + padding_left = " ", + padding_right = " ", + + hl = "MarkviewInlineCode", + }, + + issues = { + enable = true, + + default = { padding_left = " ", padding_right = " ", - hl = "MarkviewInlineCode", + icon = "󰋽 ", + + hl = "MarkviewPalette6", + }, }, - tasks = { + mentions = { + enable = true, + default = { padding_left = " ", padding_right = " ", icon = "󰋽 ", - hl = "MarkviewPalette1", + hl = "MarkviewPalette6", }, }, - issues = { + taglinks = { + enable = true, + default = { padding_left = " ", padding_right = " ", @@ -64,7 +95,176 @@ return { hl = "MarkviewPalette6", }, }, - mentions = { + + tasks = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = "󰄰 ", + + hl = "MarkviewPalette1", + }, + + ["^feat"] = { + padding_left = " ", + padding_right = " ", + + icon = "󱕅 ", + + hl = "MarkviewPalette7", + }, + + praise = { + padding_left = " ", + padding_right = " ", + + icon = "󱥋 ", + + hl = "MarkviewPalette3", + }, + + ["^suggest"] = { + padding_left = " ", + padding_right = " ", + + icon = "󰣖 ", + + hl = "MarkviewPalette2", + }, + + thought = { + padding_left = " ", + padding_right = " ", + + icon = "󰧑 ", + + hl = "MarkviewPalette0", + }, + + note = { + padding_left = " ", + padding_right = " ", + + icon = "󰠮 ", + + hl = "MarkviewPalette5", + }, + + ["^info"] = { + padding_left = " ", + padding_right = " ", + + icon = "󰋼 ", + + hl = "MarkviewPalette0", + }, + + xxx = { + padding_left = " ", + padding_right = " ", + + icon = "󰓽 ", + + hl = "MarkviewPalette0", + }, + + ["^nit"] = { + padding_left = " ", + padding_right = " ", + + icon = "󰩰 ", + + hl = "MarkviewPalette6", + }, + + ["^warn"] = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette3", + }, + + fix = { + padding_left = " ", + padding_right = " ", + + icon = "󰁨 ", + + hl = "MarkviewPalette7", + }, + + hack = { + padding_left = " ", + padding_right = " ", + + icon = "󱍔 ", + + hl = "MarkviewPalette1", + }, + + typo = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette0", + }, + + wip = { + padding_left = " ", + padding_right = " ", + + icon = "󰦖 ", + + hl = "MarkviewPalette2", + }, + + issue = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette1", + }, + + ["error"] = { + padding_left = " ", + padding_right = " ", + + icon = "󰅙 ", + + hl = "MarkviewPalette1", + }, + + fixme = { + padding_left = " ", + padding_right = " ", + + icon = "󰶯 ", + + hl = "MarkviewPalette4", + }, + + deprecated = { + padding_left = " ", + padding_right = " ", + + icon = "󰩆 ", + + hl = "MarkviewPalette1", + }, + }, + + urls = { + enable = true, + default = { padding_left = " ", padding_right = " ", From 492f4e723744cbe05d8716fa6400f4e4988076f3 Mon Sep 17 00:00:00 2001 From: Shawon Date: Fri, 9 Jan 2026 15:04:40 +0600 Subject: [PATCH 17/31] feat(comment): Added link labels for `autolinks` --- lua/markview/config/comment.lua | 306 ++++++++++++++++++++++- lua/markview/parsers/comment.lua | 1 + lua/markview/renderers/comment.lua | 131 +++++----- lua/markview/types/parsers/comment.lua | 1 + lua/markview/types/renderers/comment.lua | 27 +- 5 files changed, 395 insertions(+), 71 deletions(-) diff --git a/lua/markview/config/comment.lua b/lua/markview/config/comment.lua index 2b6706b..5bc8250 100644 --- a/lua/markview/config/comment.lua +++ b/lua/markview/config/comment.lua @@ -6,13 +6,311 @@ return { enable = true, default = { - padding_left = " ", - padding_right = " ", - icon = "󰋽 ", - hl = "MarkviewPalette6", }, + + ---|fS + + --NOTE(@OXY2DEV): Github sites. + + ["github%.com/[%a%d%-%_%.]+%/?$"] = { + --- github.com/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.label, "github%.com/([%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/?$"] = { + --- github.com// + icon = "󰳐 ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/tree/[%a%d%-%_%.]+%/?$"] = { + --- github.com///tree/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + local repo, branch = string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)/tree/([%a%d%-%_%.]+)%/?$"); + return repo .. " at " .. branch; + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+%/?$"] = { + --- github.com///commits/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+)%/?$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/releases$"] = { + --- github.com///releases + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Releases • " .. string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/releases$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/tags$"] = { + --- github.com///tags + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Tags • " .. string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/tags$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/issues$"] = { + --- github.com///issues + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Issues • " .. string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/issues$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/pulls$"] = { + --- github.com///pulls + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Pull requests • " .. string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/pulls$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/wiki$"] = { + --- github.com///wiki + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Wiki • " .. string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/wiki$"); + end + }, + + --- NOTE(@OXY2DEV): Commonly used sites by programmers. + + ["developer%.mozilla%.org"] = { + priority = -9999, + + icon = "󰖟 ", + hl = "MarkviewPalette5Fg" + }, + + ["w3schools%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette4Fg" + }, + + ["stackoverflow%.com"] = { + priority = -9999, + + icon = "󰓌 ", + hl = "MarkviewPalette2Fg" + }, + + ["reddit%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["github%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["gitlab%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["dev%.to"] = { + priority = -9999, + + icon = "󱁴 ", + hl = "MarkviewPalette0Fg" + }, + + ["codepen%.io"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["replit%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["jsfiddle%.net"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette5Fg" + }, + + ["npmjs%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette0Fg" + }, + + ["pypi%.org"] = { + priority = -9999, + + icon = "󰆦 ", + hl = "MarkviewPalette0Fg" + }, + + ["mvnrepository%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette1Fg" + }, + + ["medium%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["linkedin%.com"] = { + priority = -9999, + + icon = "󰌻 ", + hl = "MarkviewPalette5Fg" + }, + + ["news%.ycombinator%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["neovim%.io/doc/user/.*#%_?.*$"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file, tag = string.match(item.label, "neovim%.io/doc/user/(.*)#%_?(.*)$"); + --- The actual website seems to show + --- _ in the site name so, we won't + --- be replacing `_`s with ` `s. + file = string.gsub(file, "%.html$", ""); + + return string.format("%s(%s) - Neovim docs", utils.normalize_str(file), tag); + end + }, + ["neovim%.io/doc/user/.*$"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file = string.match(item.label, "neovim%.io/doc/user/(.*)$"); + file = string.gsub(file, "%.html$", ""); + + return string.format("%s - Neovim docs", utils.normalize_str(file)); + end + }, + + ["github%.com/vim/vim"] = { + priority = -100, + + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["github%.com/neovim/neovim"] = { + priority = -100, + + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["vim%.org"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["luals%.github%.io/wiki/?.*$"] = { + icon = " ", + hl = "MarkviewPalette5Fg", + + -- text = function (_, item) + -- if string.match(item.label, "luals%.github%.io/wiki/(.-)/#(.+)$") then + -- local page_mappings = { + -- annotations = { + -- ["as"] = "@as", + -- ["alias"] = "@alias", + -- ["async"] = "@async", + -- ["cast"] = "@cast", + -- ["class"] = "@class", + -- ["deprecated"] = "@deprecated", + -- ["diagnostic"] = "@diagnostic", + -- ["enum"] = "@enum", + -- ["field"] = "@field", + -- ["generic"] = "@generic", + -- ["meta"] = "@meta", + -- ["module"] = "@module", + -- ["nodiscard"] = "@nodiscard", + -- ["operator"] = "@operator", + -- ["overload"] = "@overload", + -- ["package"] = "@package", + -- ["param"] = "@param", + -- ["see"] = "@see", + -- ["source"] = "@source", + -- ["type"] = "@type", + -- ["vaarg"] = "@vaarg", + -- ["version"] = "@version" + -- } + -- }; + -- + -- local page, section = string.match(item.label, "luals%.github%.io/wiki/(.-)/#(.+)$"); + -- + -- if page_mappings[page] and page_mappings[page][section] then + -- section = page_mappings[page][section]; + -- else + -- section = utils.normalize_str(string.gsub(section, "%-", " ")); + -- end + -- + -- return string.format("%s(%s) | Lua Language Server", utils.normalize_str(page), section); + -- elseif string.match(item.label, "") then + -- local page = string.match(item.label, "luals%.github%.io/wiki/(.-)/?$"); + -- + -- return string.format("%s | Lua Language Server", utils.normalize_str(page)); + -- else + -- return item.label; + -- end + -- end + }, + + ---|fE }, code_blocks = { diff --git a/lua/markview/parsers/comment.lua b/lua/markview/parsers/comment.lua index 3fa8cc9..c33cace 100644 --- a/lua/markview/parsers/comment.lua +++ b/lua/markview/parsers/comment.lua @@ -174,6 +174,7 @@ end comment.autolink = function (_, _, text, range) comment.insert({ class = "comment_autolink", + destination = string.gsub(text[1] or "", "^%<", ""):gsub("%>$", ""), text = text, range = range, diff --git a/lua/markview/renderers/comment.lua b/lua/markview/renderers/comment.lua index 170e285..cb948d3 100644 --- a/lua/markview/renderers/comment.lua +++ b/lua/markview/renderers/comment.lua @@ -5,6 +5,72 @@ local spec = require("markview.spec"); comment.ns = vim.api.nvim_create_namespace("markview/comment"); +---@param buffer integer +---@param item markview.parsed.comment.autolinks +comment.autolink = function (buffer, item) + ---|fS + + ---@type markview.config.comment.autolinks? + local main_config = spec.get({ "comment", "autolinks" }, { fallback = nil }); + + if not main_config then + return; + end + + ---@type markview.config.comments.autolinks.opts? + local config = utils.match(main_config, item.destination or "", { + ignore_keys = { "enable" }, + eval_args = { buffer, item } + }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_col = config.text and range.col_end - 1 or range.col_start + 1, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) }, + config.text and { config.text, utils.set_hl(config.text_hl or config.hl) } or nil, + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end - 1, { + undo_restore = false, invalidate = true, + end_col = range.col_end, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + ---@param buffer integer ---@param item markview.parsed.comment.tasks comment.task = function (buffer, item) @@ -764,71 +830,6 @@ comment.taglink = function (buffer, item) ---|fE end ----@param buffer integer ----@param item markview.parsed.comment.autolinks -comment.autolink = function (buffer, item) - ---|fS - - ---@type markview.config.comment.autolinks? - local main_config = spec.get({ "comment", "autolinks" }, { fallback = nil }); - - if not main_config then - return; - end - - ---@type markview.config.__inline? - local config = utils.match(main_config, item.text[1] or "", { - ignore_keys = { "enable" }, - eval_args = { buffer, item } - }); - - if not config then - return; - end - - local range = item.range; - - vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { - undo_restore = false, invalidate = true, - end_col = range.col_start + 1, - conceal = "", - - virt_text_pos = "inline", - virt_text = { - { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, - { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, - - { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } - }, - - hl_mode = "combine" - }); - - vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { - undo_restore = false, invalidate = true, - end_row = range.row_end, - end_col = range.col_end, - - hl_group = utils.set_hl(config.hl) - }); - - vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end - 1, { - undo_restore = false, invalidate = true, - end_col = range.col_end, - conceal = "", - - virt_text_pos = "inline", - virt_text = { - { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, - { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } - }, - - hl_mode = "combine" - }); - - ---|fE -end - --- Renders HTML elements ---@param buffer integer ---@param content markview.parsed.comment[] diff --git a/lua/markview/types/parsers/comment.lua b/lua/markview/types/parsers/comment.lua index 1536a16..9dbcbec 100644 --- a/lua/markview/types/parsers/comment.lua +++ b/lua/markview/types/parsers/comment.lua @@ -12,6 +12,7 @@ An autolink. ---@class markview.parsed.comment.autolinks --- ---@field class "comment_autolink" +---@field destination string Text between `<>`. --- ---@field text string ---@field range markview.parsed.range diff --git a/lua/markview/types/renderers/comment.lua b/lua/markview/types/renderers/comment.lua index 471671d..8a18f0a 100644 --- a/lua/markview/types/renderers/comment.lua +++ b/lua/markview/types/renderers/comment.lua @@ -158,6 +158,29 @@ --- ---@field enable boolean Enable rendering of ``s. --- ----@field default markview.config.__inline Default configuration. ----@field [string] markview.config.__inline Configuration for autolinks matching the key's pattern. +---@field default markview.config.comments.autolinks.opts Default configuration. +---@field [string] markview.config.comments.autolinks.opts Configuration for autolinks matching the key's pattern. + + +---@class markview.config.comments.autolinks.opts +--- +---@field corner_left? string Left corner. +---@field corner_left_hl? string Highlight group for the left corner. +--- +---@field padding_left? string Left padding(added after `corner_left`). +---@field padding_left_hl? string Highlight group for the left padding. +--- +---@field icon? string Icon(added after `padding_left`). +---@field icon_hl? string Highlight group for the icon. +--- +---@field text? string Text to show instead of the `autolink`. +---@field text_hl? string Highlight group for the shown text. +--- +---@field hl? string Default highlight group(used by `*_hl` options when they are not set). +--- +---@field padding_right? string Right padding. +---@field padding_right_hl? string Highlight group for the right padding. +--- +---@field corner_right? string Right corner(added after `padding_right`). +---@field corner_right_hl? string Highlight group for the right corner. From a675d45be8488400707827de8387b87688ad17be Mon Sep 17 00:00:00 2001 From: Shawon Date: Fri, 9 Jan 2026 15:17:57 +0600 Subject: [PATCH 18/31] refactor(config, comment, issues): Updated `icon` & `hl` --- lua/markview/config/comment.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/markview/config/comment.lua b/lua/markview/config/comment.lua index 5bc8250..38932ee 100644 --- a/lua/markview/config/comment.lua +++ b/lua/markview/config/comment.lua @@ -362,9 +362,9 @@ return { padding_left = " ", padding_right = " ", - icon = "󰋽 ", + icon = " ", - hl = "MarkviewPalette6", + hl = "MarkviewPalette2", }, }, From e4bd8cf4745408554a869e4bf928c54a3c73cfa1 Mon Sep 17 00:00:00 2001 From: Shawon Date: Fri, 9 Jan 2026 15:23:47 +0600 Subject: [PATCH 19/31] refactor(config, comment, mentions): Updated `icon` & `hl` --- lua/markview/config/comment.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/markview/config/comment.lua b/lua/markview/config/comment.lua index 38932ee..2fc4205 100644 --- a/lua/markview/config/comment.lua +++ b/lua/markview/config/comment.lua @@ -375,9 +375,9 @@ return { padding_left = " ", padding_right = " ", - icon = "󰋽 ", + icon = " ", - hl = "MarkviewPalette6", + hl = "MarkviewPalette5", }, }, From fa27d360d8f0da66b4e71033d993c99175b9c010 Mon Sep 17 00:00:00 2001 From: Shawon Date: Fri, 9 Jan 2026 16:25:03 +0600 Subject: [PATCH 20/31] refactor(config, comment, urls): Improved rendering --- lua/markview/config/comment.lua | 438 +++++++++++++++++++---- lua/markview/parsers/comment.lua | 1 + lua/markview/renderers/comment.lua | 11 +- lua/markview/types/parsers/comment.lua | 1 + lua/markview/types/renderers/comment.lua | 35 +- 5 files changed, 413 insertions(+), 73 deletions(-) diff --git a/lua/markview/config/comment.lua b/lua/markview/config/comment.lua index 2fc4205..c16b5cb 100644 --- a/lua/markview/config/comment.lua +++ b/lua/markview/config/comment.lua @@ -1,3 +1,12 @@ +local function normalize_str(str) + if type(str) ~= "string" then + return ""; + end + + return string.lower(str):gsub("^%l", string.upper); +end + + ---@type markview.config.comment return { enable = true, @@ -20,7 +29,7 @@ return { hl = "MarkviewPalette0Fg", text = function (_, item) - return string.match(item.label, "github%.com/([%a%d%-%_%.]+)%/?$"); + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+)%/?$"); end }, ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/?$"] = { @@ -29,7 +38,7 @@ return { hl = "MarkviewPalette0Fg", text = function (_, item) - return string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/?$"); + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/?$"); end }, ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/tree/[%a%d%-%_%.]+%/?$"] = { @@ -38,7 +47,7 @@ return { hl = "MarkviewPalette0Fg", text = function (_, item) - local repo, branch = string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)/tree/([%a%d%-%_%.]+)%/?$"); + local repo, branch = string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)/tree/([%a%d%-%_%.]+)%/?$"); return repo .. " at " .. branch; end }, @@ -48,7 +57,7 @@ return { hl = "MarkviewPalette0Fg", text = function (_, item) - return string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+)%/?$"); + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+)%/?$"); end }, @@ -58,7 +67,7 @@ return { hl = "MarkviewPalette0Fg", text = function (_, item) - return "Releases • " .. string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/releases$"); + return "Releases • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/releases$"); end }, ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/tags$"] = { @@ -67,7 +76,7 @@ return { hl = "MarkviewPalette0Fg", text = function (_, item) - return "Tags • " .. string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/tags$"); + return "Tags • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/tags$"); end }, ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/issues$"] = { @@ -76,7 +85,7 @@ return { hl = "MarkviewPalette0Fg", text = function (_, item) - return "Issues • " .. string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/issues$"); + return "Issues • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/issues$"); end }, ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/pulls$"] = { @@ -85,7 +94,7 @@ return { hl = "MarkviewPalette0Fg", text = function (_, item) - return "Pull requests • " .. string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/pulls$"); + return "Pull requests • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/pulls$"); end }, @@ -95,7 +104,7 @@ return { hl = "MarkviewPalette0Fg", text = function (_, item) - return "Wiki • " .. string.match(item.label, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/wiki$"); + return "Wiki • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/wiki$"); end }, @@ -218,13 +227,13 @@ return { hl = "MarkviewPalette4Fg", text = function (_, item) - local file, tag = string.match(item.label, "neovim%.io/doc/user/(.*)#%_?(.*)$"); + local file, tag = string.match(item.destination, "neovim%.io/doc/user/(.*)#%_?(.*)$"); --- The actual website seems to show --- _ in the site name so, we won't --- be replacing `_`s with ` `s. file = string.gsub(file, "%.html$", ""); - return string.format("%s(%s) - Neovim docs", utils.normalize_str(file), tag); + return string.format("%s(%s) - Neovim docs", normalize_str(file), tag); end }, ["neovim%.io/doc/user/.*$"] = { @@ -232,10 +241,10 @@ return { hl = "MarkviewPalette4Fg", text = function (_, item) - local file = string.match(item.label, "neovim%.io/doc/user/(.*)$"); + local file = string.match(item.destination, "neovim%.io/doc/user/(.*)$"); file = string.gsub(file, "%.html$", ""); - return string.format("%s - Neovim docs", utils.normalize_str(file)); + return string.format("%s - Neovim docs", normalize_str(file)); end }, @@ -262,52 +271,52 @@ return { icon = " ", hl = "MarkviewPalette5Fg", - -- text = function (_, item) - -- if string.match(item.label, "luals%.github%.io/wiki/(.-)/#(.+)$") then - -- local page_mappings = { - -- annotations = { - -- ["as"] = "@as", - -- ["alias"] = "@alias", - -- ["async"] = "@async", - -- ["cast"] = "@cast", - -- ["class"] = "@class", - -- ["deprecated"] = "@deprecated", - -- ["diagnostic"] = "@diagnostic", - -- ["enum"] = "@enum", - -- ["field"] = "@field", - -- ["generic"] = "@generic", - -- ["meta"] = "@meta", - -- ["module"] = "@module", - -- ["nodiscard"] = "@nodiscard", - -- ["operator"] = "@operator", - -- ["overload"] = "@overload", - -- ["package"] = "@package", - -- ["param"] = "@param", - -- ["see"] = "@see", - -- ["source"] = "@source", - -- ["type"] = "@type", - -- ["vaarg"] = "@vaarg", - -- ["version"] = "@version" - -- } - -- }; - -- - -- local page, section = string.match(item.label, "luals%.github%.io/wiki/(.-)/#(.+)$"); - -- - -- if page_mappings[page] and page_mappings[page][section] then - -- section = page_mappings[page][section]; - -- else - -- section = utils.normalize_str(string.gsub(section, "%-", " ")); - -- end - -- - -- return string.format("%s(%s) | Lua Language Server", utils.normalize_str(page), section); - -- elseif string.match(item.label, "") then - -- local page = string.match(item.label, "luals%.github%.io/wiki/(.-)/?$"); - -- - -- return string.format("%s | Lua Language Server", utils.normalize_str(page)); - -- else - -- return item.label; - -- end - -- end + text = function (_, item) + if string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$") then + local page_mappings = { + annotations = { + ["as"] = "@as", + ["alias"] = "@alias", + ["async"] = "@async", + ["cast"] = "@cast", + ["class"] = "@class", + ["deprecated"] = "@deprecated", + ["diagnostic"] = "@diagnostic", + ["enum"] = "@enum", + ["field"] = "@field", + ["generic"] = "@generic", + ["meta"] = "@meta", + ["module"] = "@module", + ["nodiscard"] = "@nodiscard", + ["operator"] = "@operator", + ["overload"] = "@overload", + ["package"] = "@package", + ["param"] = "@param", + ["see"] = "@see", + ["source"] = "@source", + ["type"] = "@type", + ["vaarg"] = "@vaarg", + ["version"] = "@version" + } + }; + + local page, section = string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$"); + + if page_mappings[page] and page_mappings[page][section] then + section = page_mappings[page][section]; + else + section = normalize_str(string.gsub(section, "%-", " ")); + end + + return string.format("%s(%s) | Lua Language Server", normalize_str(page), section); + elseif string.match(item.destination, "") then + local page = string.match(item.destination, "luals%.github%.io/wiki/(.-)/?$"); + + return string.format("%s | Lua Language Server", normalize_str(page)); + else + return item.destination; + end + end }, ---|fE @@ -388,9 +397,9 @@ return { padding_left = " ", padding_right = " ", - icon = "󰋽 ", + icon = "󰌷 ", - hl = "MarkviewPalette6", + hl = "MarkviewHyperlink", }, }, @@ -564,12 +573,311 @@ return { enable = true, default = { - padding_left = " ", - padding_right = " ", + icon = "󰌷 ", - icon = "󰋽 ", + hl = "MarkviewHyperlink", + }, - hl = "MarkviewPalette6", + ---|fS + + --NOTE(@OXY2DEV): Github sites. + + ["github%.com/[%a%d%-%_%.]+%/?$"] = { + --- github.com/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/?$"] = { + --- github.com// + icon = "󰳐 ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/tree/[%a%d%-%_%.]+%/?$"] = { + --- github.com///tree/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + local repo, branch = string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)/tree/([%a%d%-%_%.]+)%/?$"); + return repo .. " at " .. branch; + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+%/?$"] = { + --- github.com///commits/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+)%/?$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/releases$"] = { + --- github.com///releases + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Releases • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/releases$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/tags$"] = { + --- github.com///tags + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Tags • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/tags$"); + end }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/issues$"] = { + --- github.com///issues + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Issues • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/issues$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/pulls$"] = { + --- github.com///pulls + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Pull requests • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/pulls$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/wiki$"] = { + --- github.com///wiki + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Wiki • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/wiki$"); + end + }, + + --- NOTE(@OXY2DEV): Commonly used sites by programmers. + + ["developer%.mozilla%.org"] = { + priority = -9999, + + icon = "󰖟 ", + hl = "MarkviewPalette5Fg" + }, + + ["w3schools%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette4Fg" + }, + + ["stackoverflow%.com"] = { + priority = -9999, + + icon = "󰓌 ", + hl = "MarkviewPalette2Fg" + }, + + ["reddit%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["github%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["gitlab%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["dev%.to"] = { + priority = -9999, + + icon = "󱁴 ", + hl = "MarkviewPalette0Fg" + }, + + ["codepen%.io"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["replit%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["jsfiddle%.net"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette5Fg" + }, + + ["npmjs%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette0Fg" + }, + + ["pypi%.org"] = { + priority = -9999, + + icon = "󰆦 ", + hl = "MarkviewPalette0Fg" + }, + + ["mvnrepository%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette1Fg" + }, + + ["medium%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["linkedin%.com"] = { + priority = -9999, + + icon = "󰌻 ", + hl = "MarkviewPalette5Fg" + }, + + ["news%.ycombinator%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["neovim%.io/doc/user/.*#%_?.*$"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file, tag = string.match(item.destination, "neovim%.io/doc/user/(.*)#%_?(.*)$"); + --- The actual website seems to show + --- _ in the site name so, we won't + --- be replacing `_`s with ` `s. + file = string.gsub(file, "%.html$", ""); + + return string.format("%s(%s) - Neovim docs", normalize_str(file), tag); + end + }, + ["neovim%.io/doc/user/.*$"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file = string.match(item.destination, "neovim%.io/doc/user/(.*)$"); + file = string.gsub(file, "%.html$", ""); + + return string.format("%s - Neovim docs", normalize_str(file)); + end + }, + + ["github%.com/vim/vim"] = { + priority = -100, + + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["github%.com/neovim/neovim"] = { + priority = -100, + + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["vim%.org"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["luals%.github%.io/wiki/?.*$"] = { + icon = " ", + hl = "MarkviewPalette5Fg", + + text = function (_, item) + if string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$") then + local page_mappings = { + annotations = { + ["as"] = "@as", + ["alias"] = "@alias", + ["async"] = "@async", + ["cast"] = "@cast", + ["class"] = "@class", + ["deprecated"] = "@deprecated", + ["diagnostic"] = "@diagnostic", + ["enum"] = "@enum", + ["field"] = "@field", + ["generic"] = "@generic", + ["meta"] = "@meta", + ["module"] = "@module", + ["nodiscard"] = "@nodiscard", + ["operator"] = "@operator", + ["overload"] = "@overload", + ["package"] = "@package", + ["param"] = "@param", + ["see"] = "@see", + ["source"] = "@source", + ["type"] = "@type", + ["vaarg"] = "@vaarg", + ["version"] = "@version" + } + }; + + local page, section = string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$"); + + if page_mappings[page] and page_mappings[page][section] then + section = page_mappings[page][section]; + else + section = normalize_str(string.gsub(section, "%-", " ")); + end + + return string.format("%s(%s) | Lua Language Server", normalize_str(page), section); + elseif string.match(item.destination, "") then + local page = string.match(item.destination, "luals%.github%.io/wiki/(.-)/?$"); + + return string.format("%s | Lua Language Server", normalize_str(page)); + else + return item.destination; + end + end + }, + + ---|fE }, }; diff --git a/lua/markview/parsers/comment.lua b/lua/markview/parsers/comment.lua index c33cace..6a120a3 100644 --- a/lua/markview/parsers/comment.lua +++ b/lua/markview/parsers/comment.lua @@ -162,6 +162,7 @@ end comment.url = function (_, _, text, range) comment.insert({ class = "comment_url", + destination = text[1] or "", text = text, range = range, diff --git a/lua/markview/renderers/comment.lua b/lua/markview/renderers/comment.lua index cb948d3..06b43ab 100644 --- a/lua/markview/renderers/comment.lua +++ b/lua/markview/renderers/comment.lua @@ -404,8 +404,6 @@ comment.code_block = function (buffer, item) return; end - -- vim.print(item) - local decorations = require("markview.filetypes").get(item.language); local label = { string.format(" %s%s ", decorations.icon, decorations.name), config.label_hl or decorations.icon_hl }; local win = utils.buf_getwin(buffer); @@ -716,8 +714,8 @@ comment.url = function (buffer, item) return; end - ---@type markview.config.__inline? - local config = utils.match(main_config, item.text[1] or "", { + ---@type markview.config.comments.urls.opts? + local config = utils.match(main_config, item.destination or "", { ignore_keys = { "enable" }, eval_args = { buffer, item } }); @@ -730,13 +728,16 @@ comment.url = function (buffer, item) vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { undo_restore = false, invalidate = true, + end_col = config.text and range.col_end or nil, + conceal = config.text and "" or nil, virt_text_pos = "inline", virt_text = { { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, - { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) }, + config.text and { config.text, utils.set_hl(config.text_hl or config.hl) } or nil, }, hl_mode = "combine" diff --git a/lua/markview/types/parsers/comment.lua b/lua/markview/types/parsers/comment.lua index 9dbcbec..d15a9f7 100644 --- a/lua/markview/types/parsers/comment.lua +++ b/lua/markview/types/parsers/comment.lua @@ -57,6 +57,7 @@ An autolink. ---@class markview.parsed.comment.urls --- ---@field class "comment_url" +---@field destination string --- ---@field text string ---@field range markview.parsed.range diff --git a/lua/markview/types/renderers/comment.lua b/lua/markview/types/renderers/comment.lua index 8a18f0a..3842870 100644 --- a/lua/markview/types/renderers/comment.lua +++ b/lua/markview/types/renderers/comment.lua @@ -137,8 +137,34 @@ --- ---@field enable boolean Enable rendering of `URL`s. --- ----@field default markview.config.__inline Default configuration for URLs. ----@field [string] markview.config.__inline Configuration for URLs whose text matches with the key's pattern. +---@field default markview.config.comments.urls.opts Default configuration for URLs. +---@field [string] markview.config.comments.urls.opts Configuration for URLs whose text matches with the key's pattern. + + +---@class markview.config.comments.urls.opts +--- +---@field corner_left? string Left corner. +---@field corner_left_hl? string Highlight group for the left corner. +--- +---@field padding_left? string Left padding(added after `corner_left`). +---@field padding_left_hl? string Highlight group for the left padding. +--- +---@field icon? string Icon(added after `padding_left`). +---@field icon_hl? string Highlight group for the icon. +--- +--[[ Text to show instead of the `autolink`.]] +---@field text? +---| string +---| function(buffer: integer, item: markview.parsed.comment.autolinks): string +---@field text_hl? string Highlight group for the shown text. +--- +---@field hl? string Default highlight group(used by `*_hl` options when they are not set). +--- +---@field padding_right? string Right padding. +---@field padding_right_hl? string Highlight group for the right padding. +--- +---@field corner_right? string Right corner(added after `padding_right`). +---@field corner_right_hl? string Highlight group for the right corner. ------------------------------------------------------------------------------ @@ -173,7 +199,10 @@ ---@field icon? string Icon(added after `padding_left`). ---@field icon_hl? string Highlight group for the icon. --- ----@field text? string Text to show instead of the `autolink`. +--[[ Text to show instead of the `autolink`.]] +---@field text? +---| string +---| function(buffer: integer, item: markview.parsed.comment.autolinks): string ---@field text_hl? string Highlight group for the shown text. --- ---@field hl? string Default highlight group(used by `*_hl` options when they are not set). From 05a6d53d5a871d7e8ff835bafdf3d7faf5aa3426 Mon Sep 17 00:00:00 2001 From: Shawon Date: Fri, 9 Jan 2026 22:21:09 +0600 Subject: [PATCH 21/31] feat(comment): Added compatibilty for legacy parser --- lua/markview/parsers/comment.lua | 105 +++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/lua/markview/parsers/comment.lua b/lua/markview/parsers/comment.lua index 6a120a3..d49a910 100644 --- a/lua/markview/parsers/comment.lua +++ b/lua/markview/parsers/comment.lua @@ -50,6 +50,111 @@ comment.task = function (buffer, TSNode, text, range) }); end +--- Tasks(legacy parser). +---@param buffer integer +---@param TSNode TSNode +---@param text string[] +---@param range markview.parsed.comment.tasks.range +comment.tag = function (buffer, TSNode, text, range) + local kind; + + for child in TSNode:iter_children() do + if child:type() == "name" then + kind = child; + range.kind = { child:range() }; + + range.label_row_end = range.row_start; + range.label_col_end = range.kind[4] + 1; -- `:` is part of the label! + elseif child:type() == "user" then + local user_range = { child:range() }; + + range.label_row_end = range.row_start; + range.label_col_end = user_range[4] + 2; -- `:` is part of the label! + + -- Add special syntax support for scope text. + comment.tag_scope(buffer, child, { vim.treesitter.get_node_text(child, buffer, {}) }, user_range); + end + end + + if not kind then + return; + end + + comment.insert({ + class = "comment_task", + kind = vim.treesitter.get_node_text(kind, buffer, {}), + + text = text, + range = range, + }); +end + +--- Tasks scope parser(legacy parser). +---@param buffer integer +---@param _ TSNode +---@param text string[] +---@param root_range markview.parsed.comment.tasks.range +comment.tag_scope = function (buffer, _, text, root_range) + local lpeg = vim.lpeg; + + local function as_wspace (m) return { kind = "space", value = m }; end + local function as_comma (m) return { kind = "comma", value = m }; end + + local function as_issue (m) return { kind = "issue", value = m }; end + local function as_mention (m) return { kind = "mention", value = m }; end + local function as_word (m) return { kind = "word", value = m }; end + + local space = lpeg.C( lpeg.S(" \t\n\r") ) / as_wspace; + local comma = lpeg.C( lpeg.P(",") ) / as_comma; + + local walnum = lpeg.R("az", "AZ", "09"); + local non_wspacse = 1 - ( space + comma ); + local word = lpeg.C( walnum * (non_wspacse^0) ) / as_word; + + local mention = lpeg.C( lpeg.P("@") * (non_wspacse^1) ) / as_mention; + + local num_issue = lpeg.C( lpeg.P("#") * ( lpeg.R("09") ^ 1 ) ) / as_issue; + + local invalid_cahrs = space + lpeg.P("#"); + local issue_name = lpeg.R("az", "AZ", "09") * (1 - invalid_cahrs)^0; + local desc_issue = lpeg.C( issue_name * lpeg.P("#") * ( lpeg.R("09") ^ 1 ) ) / as_issue; + + local token = space + comma + desc_issue + num_issue + mention + word; + local scope = lpeg.Ct(token^0); + + local col_start = root_range[2]; + + for _, item in ipairs(lpeg.match(scope, text[1] or "")) do + if item.kind == "word" then + comment.task_scope(buffer, nil, { item.value }, { + row_start = root_range[1], + col_start = col_start, + + row_end = root_range[3], + col_end = col_start + #item.value, + }); + elseif item.kind == "issue" then + comment.issue(buffer, nil, { item.value }, { + row_start = root_range[1], + col_start = col_start, + + row_end = root_range[3], + col_end = col_start + #item.value, + }); + elseif item.kind == "mention" then + comment.mention(buffer, nil, { item.value }, { + row_start = root_range[1], + col_start = col_start, + + row_end = root_range[3], + col_end = col_start + #item.value, + }); + end + + col_start = col_start + #item.value; + end +end + --- Issue. ---@param text string[] ---@param range markview.parsed.range From 6c07f8f01fe76c6a4da774e1212a23b7671ace3e Mon Sep 17 00:00:00 2001 From: Shawon Date: Fri, 9 Jan 2026 23:28:35 +0600 Subject: [PATCH 22/31] feat(comment): Added task scopes support --- lua/markview/config/comment.lua | 13 +++++++++++++ lua/markview/renderers/comment.lua | 6 +++--- lua/markview/types/parsers/comment.lua | 12 ++++++++++++ lua/markview/types/renderers/comment.lua | 11 +++++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lua/markview/config/comment.lua b/lua/markview/config/comment.lua index c16b5cb..1f1f6ee 100644 --- a/lua/markview/config/comment.lua +++ b/lua/markview/config/comment.lua @@ -569,6 +569,19 @@ return { }, }, + task_scopes = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = "󰈲 ", + + hl = "MarkviewPalette4", + }, + }, + urls = { enable = true, diff --git a/lua/markview/renderers/comment.lua b/lua/markview/renderers/comment.lua index 06b43ab..d5b1944 100644 --- a/lua/markview/renderers/comment.lua +++ b/lua/markview/renderers/comment.lua @@ -149,18 +149,18 @@ comment.task = function (buffer, item) end ---@param buffer integer ----@param item markview.parsed.comment.issues +---@param item markview.parsed.comment.task_scopes comment.task_scope = function (buffer, item) ---|fS - ---@type markview.config.comment.tasks? + ---@type markview.config.comment.task_scopes? local main_config = spec.get({ "comment", "task_scopes" }, { fallback = nil }); if not main_config then return; end - ---@type markview.config.comment.tasks.opts? + ---@type markview.config.__inline? local config = utils.match(main_config, item.text[1] or "", { ignore_keys = { "enable" }, eval_args = { buffer, item } diff --git a/lua/markview/types/parsers/comment.lua b/lua/markview/types/parsers/comment.lua index d15a9f7..b2a6f83 100644 --- a/lua/markview/types/parsers/comment.lua +++ b/lua/markview/types/parsers/comment.lua @@ -43,6 +43,16 @@ An autolink. ------------------------------------------------------------------------------ +--- A `task` scope. +---@class markview.parsed.comment.task_scopes +--- +---@field class "comment_task_scopes" +--- +---@field text string +---@field range markview.parsed.comment.tasks.range + +------------------------------------------------------------------------------ + --- An issue reference. ---@class markview.parsed.comment.issues --- @@ -130,6 +140,7 @@ An autolink. ---| markview.parsed.comment.mentions ---| markview.parsed.comment.taglinks ---| markview.parsed.comment.tasks +---| markview.parsed.comment.task_scopes ---| markview.parsed.comment.urls @@ -142,5 +153,6 @@ An autolink. ---@field mentions markview.parsed.comment.mentions[] ---@field taglinks markview.parsed.comment.taglinks[] ---@field tasks markview.parsed.comment.tasks[] +---@field task_scopes markview.parsed.comment.task_scopes[] ---@field urls markview.parsed.comment.urls[] diff --git a/lua/markview/types/renderers/comment.lua b/lua/markview/types/renderers/comment.lua index 3842870..53afc21 100644 --- a/lua/markview/types/renderers/comment.lua +++ b/lua/markview/types/renderers/comment.lua @@ -14,6 +14,7 @@ ---@field mentions markview.config.comment.mentions ---@field taglinks markview.config.comment.taglinks ---@field tasks markview.config.comment.tasks +---@field task_scopes markview.config.comment.task_scopes ---@field urls markview.config.comment.urls ------------------------------------------------------------------------------ @@ -132,6 +133,16 @@ ------------------------------------------------------------------------------ +--- Configuration for task_scopes. +---@class markview.config.comment.task_scopes +--- +---@field enable boolean Enable rendering of `task scope`s. +--- +---@field default markview.config.__inline Default configuration for mentions. +---@field [string] markview.config.__inline Configuration for scopes matching the key's pattern. + +------------------------------------------------------------------------------ + --- Configuration for URLs. ---@class markview.config.comment.urls --- From d92f4d3fdef5b1e80011dd42ef72a008d901b3ab Mon Sep 17 00:00:00 2001 From: Shawon Date: Sat, 10 Jan 2026 14:46:07 +0600 Subject: [PATCH 23/31] fix(config, condition): Parity between `can_attach()` & `buf_handle()` Both now have same behavior. --- lua/markview/autocmds.lua | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/lua/markview/autocmds.lua b/lua/markview/autocmds.lua index cbb5976..e709c9a 100644 --- a/lua/markview/autocmds.lua +++ b/lua/markview/autocmds.lua @@ -86,15 +86,27 @@ autocmds.should_detach = function (args) local condition = spec.get({ "preview", "condition" }, { eval_args = { args.buf } }); - if vim.list_contains(ignore_bt, bt) == true then - return true; - elseif vim.list_contains(attach_ft, ft) == false then - return true; - elseif condition == false then - return true; + --[[ + feat: Attaching to buffers. + + If condition is `true`(either `preview.condition = true` or the evaluated function value is `true`), attach to `buffer`. + + Otherwise, check if the **buftype** is included in `preview.ignore_buftypes`. If it is then we don't attach to `buffer`. + Then check if the **filetype** is included in `preview.filetypes`. IF it is we attach to `buffer`. + ]] + if condition == nil then + -- No condition specified. + + if vim.list_contains(ignore_bt, bt) == true then + --- Ignored buffer type. + return true; + elseif vim.list_contains(attach_ft, ft) == false then + --- Ignored file type. + return true; + end end - return false; + return condition == false; ---|fE end From 883646bce69723d0ad81eccd0bbdd5b596d4bd1f Mon Sep 17 00:00:00 2001 From: Shawon Date: Sat, 10 Jan 2026 17:05:59 +0600 Subject: [PATCH 24/31] refactor(comment, hybrid_mode): Added option maps for `comment` --- lua/markview/renderer.lua | 9 ++++++++- lua/markview/types/markview.lua | 1 + lua/markview/types/preview.lua | 22 ++++++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lua/markview/renderer.lua b/lua/markview/renderer.lua index 8bbe4b2..20c188d 100644 --- a/lua/markview/renderer.lua +++ b/lua/markview/renderer.lua @@ -15,7 +15,14 @@ renderer.__filter_cache = { renderer.option_maps = { ---|fS - doxtext = { + comment = { + autolinks = { "comment_autolink" }, + code_blocks = { "comment_code_block" }, + inline_codes = { "comment_inline_code" }, + issues = { "comment_issue" }, + mentions = { "comment_mention" }, + taglinks = { "comment_taglink" }, + task_scopes = { "comment_task_scope" }, tasks = { "comment_task" }, }, html = { diff --git a/lua/markview/types/markview.lua b/lua/markview/types/markview.lua index ecc1f72..c814423 100644 --- a/lua/markview/types/markview.lua +++ b/lua/markview/types/markview.lua @@ -100,6 +100,7 @@ --- Maps a `node_type` to an option name. ---@class markview.renderer.option_maps --- +---@field comment markview.renderer.option_map ---@field html markview.renderer.option_map ---@field latex markview.renderer.option_map ---@field markdown markview.renderer.option_map diff --git a/lua/markview/types/preview.lua b/lua/markview/types/preview.lua index 8c77511..dfa5574 100644 --- a/lua/markview/types/preview.lua +++ b/lua/markview/types/preview.lua @@ -58,6 +58,7 @@ --- in `hybrid mode`. ---@class markview.config.preview.raw --- +---@field comment? markview.config.preview.raw.comment[] ---@field html? markview.config.preview.raw.html[] ---@field latex? markview.config.preview.raw.latex[] ---@field markdown? markview.config.preview.raw.markdown[] @@ -65,6 +66,27 @@ ---@field typst? markview.config.preview.raw.typst[] ---@field yaml? markview.config.preview.raw.yaml[] +---@alias markview.config.preview.raw.comment +---| "!autolinks" +---| "!code_blocks" +---| "!inline_codes" +---| "!issues" +---| "!mentions" +---| "!taglinks" +---| "!task_scopes" +---| "!tasks" +---| "!urls" +--- +---| "autolinks" +---| "code_blocks" +---| "inline_codes" +---| "issues" +---| "mentions" +---| "taglinks" +---| "task_scopes" +---| "tasks" +---| "urls" + ---@alias markview.config.preview.raw.html ---| "!container_elements" ---| "!headings" From c420afdf3dad8cc240c635c437a6bfb9c7aeb557 Mon Sep 17 00:00:00 2001 From: Shawon Date: Sat, 10 Jan 2026 17:06:26 +0600 Subject: [PATCH 25/31] chore: Updated option map key orders --- lua/markview/renderer.lua | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lua/markview/renderer.lua b/lua/markview/renderer.lua index 20c188d..3beaf54 100644 --- a/lua/markview/renderer.lua +++ b/lua/markview/renderer.lua @@ -24,6 +24,7 @@ renderer.option_maps = { taglinks = { "comment_taglink" }, task_scopes = { "comment_task_scope" }, tasks = { "comment_task" }, + urls = { "comment_url" }, }, html = { container_elements = { "html_container_element" }, @@ -44,31 +45,30 @@ renderer.option_maps = { }, markdown = { block_quotes = { "markdown_block_quote" }, + checkboxes = { "markdown_checkbox" }, code_blocks = { "markdown_code_block" }, headings = { "markdown_atx_heading", "markdown_setext_heading" }, horizontal_rules = { "markdown_hr" }, list_items = { "markdown_list_item" }, metadata_minus = { "markdown_metadata_minus" }, metadata_plus = { "markdown_metadata_plus" }, - tables = { "markdown_table" }, reference_definitions = { "markdown_link_ref_definition" }, - - checkboxes = { "markdown_checkbox" }, + tables = { "markdown_table" }, }, markdown_inline = { + block_references = { "inline_link_block_ref" }, checkboxes = { "inline_checkbox" }, - inline_codes = { "inline_code_span" }, + emails = { "inline_link_email" }, + embed_files = { "inline_embed_files" }, entities = { "inline_entity" }, escapes = { "inline_escaped" }, footnotes = { "inline_footnote" }, highlights = { "inline_highlight" }, - block_references = { "inline_link_block_ref" }, - embed_files = { "inline_embed_files" }, - emails = { "inline_link_email" }, hyperlinks = { "inline_link_hyperlink", "inline_link_shortcut" }, images = { "inline_link_image" }, - uri_autolinks = { "inline_link_uri_autolink" }, + inline_codes = { "inline_code_span" }, internal_links = { "inline_link_internal" }, + uri_autolinks = { "inline_link_uri_autolink" }, }, typst = { code_blocks = { "typst_code_block" }, @@ -77,16 +77,16 @@ renderer.option_maps = { headings = { "typst_heading" }, labels = { "typst_label" }, list_items = { "typst_list_item" }, - reference_links = { "typst_link_ref" }, - url_links = { "typst_link_url" }, math_blocks = { "typst_math_blocks" }, math_spans = { "typst_math_spans" }, raw_blocks = { "typst_raw_block" }, raw_spans = { "typst_raw_span" }, + reference_links = { "typst_link_ref" }, subscripts = { "typst_subscript" }, superscripts = { "typst_superscript" }, symbols = { "typst_symbol" }, terms = { "typst_terms" }, + url_links = { "typst_link_url" }, }, yaml = { properties = { "yaml_property" }, From 87d74af3f0c0a811080fc5412d8b9c5526573700 Mon Sep 17 00:00:00 2001 From: Shawon Date: Sun, 11 Jan 2026 20:37:53 +0600 Subject: [PATCH 26/31] feat(comment): Added `bold` & `italic` support --- lua/markview/config/comment.lua | 8 ++ lua/markview/parsers/comment.lua | 27 +++++++ lua/markview/renderers/comment.lua | 118 ++++++++++++++++++++++++++++- 3 files changed, 151 insertions(+), 2 deletions(-) diff --git a/lua/markview/config/comment.lua b/lua/markview/config/comment.lua index 1f1f6ee..f24b666 100644 --- a/lua/markview/config/comment.lua +++ b/lua/markview/config/comment.lua @@ -322,6 +322,10 @@ return { ---|fE }, + bolds = { + enable = true, + }, + code_blocks = { enable = true, @@ -377,6 +381,10 @@ return { }, }, + italics = { + enable = true, + }, + mentions = { enable = true, diff --git a/lua/markview/parsers/comment.lua b/lua/markview/parsers/comment.lua index d49a910..4f654dc 100644 --- a/lua/markview/parsers/comment.lua +++ b/lua/markview/parsers/comment.lua @@ -167,6 +167,30 @@ comment.task_scope = function (_, _, text, range) }); end +--- Issue. +---@param text string[] +---@param range markview.parsed.range +comment.bold = function (_, _, text, range) + comment.insert({ + class = "comment_bold", + + text = text, + range = range, + }); +end + +--- Issue. +---@param text string[] +---@param range markview.parsed.range +comment.italic = function (_, _, text, range) + comment.insert({ + class = "comment_italic", + + text = text, + range = range, + }); +end + --- Issue. ---@param text string[] ---@param range markview.parsed.range @@ -325,6 +349,9 @@ comment.parse = function (buffer, TSTree, from, to) (task_scope (word) @comment.task_scope) + (bold) @comment.bold + (italic) @comment.italic + (code) @comment.inline_code (code_block) @comment.code_block diff --git a/lua/markview/renderers/comment.lua b/lua/markview/renderers/comment.lua index d5b1944..1774275 100644 --- a/lua/markview/renderers/comment.lua +++ b/lua/markview/renderers/comment.lua @@ -831,10 +831,122 @@ comment.taglink = function (buffer, item) ---|fE end ---- Renders HTML elements +---@param buffer integer +---@param item markview.parsed.comment.inline_codes +comment.bold = function (buffer, item) + ---|fS + + ---@type markview.config.comment.bolds? + local config = spec.get({ "comment", "bolds" }, { fallback = nil }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_col = range.col_start + 2, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end - 2, { + undo_restore = false, invalidate = true, + end_col = range.col_end, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + +---@param buffer integer +---@param item markview.parsed.comment.inline_codes +comment.italic = function (buffer, item) + ---|fS + + ---@type markview.config.comment.italics? + local config = spec.get({ "comment", "italics" }, { fallback = nil }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_col = range.col_start + 1, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end - 1, { + undo_restore = false, invalidate = true, + end_col = range.col_end, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + +--- Renders fancy comments ---@param buffer integer ---@param content markview.parsed.comment[] comment.render = function (buffer, content) + ---|fS + local custom = spec.get({ "renderers" }, { fallback = {} }); for _, item in ipairs(content or {}) do @@ -859,9 +971,11 @@ comment.render = function (buffer, content) }); end end + + ---|fE end ---- Clears decorations of HTML elements +--- Clears decorations of fancy comments ---@param buffer integer ---@param from integer ---@param to integer From 339ad1676d12964ce3d3505f7e48ad21694cbc7c Mon Sep 17 00:00:00 2001 From: Shawon Date: Sun, 11 Jan 2026 23:41:14 +0600 Subject: [PATCH 27/31] chore: Added test file for `comment` --- test/comment.lua | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 test/comment.lua diff --git a/test/comment.lua b/test/comment.lua new file mode 100644 index 0000000..057def4 --- /dev/null +++ b/test/comment.lua @@ -0,0 +1,32 @@ +--[[ +feat(@OXY2DEV): Tree-sitter parser for `Conventional comments`. + +A `tree-sitter` parser for **conventional comments** that supports a subset of `markdown`. +It can be used as an injected language for other parsers(e.g. for comments). + +The parser currently supports, + + • **Bold** + • *Italic* + • `Code` + • 'Quoted_text' + • "Double quoted text" + • @mentions + • issues/reference#52 + • https://example.com + • |help-section| + +```lua +print("Hello, world!"); +``` + +With support for *common comment topics* such as, + +todo: Some task. +FIXME: Fix some *issues*. + +NOTE(grammar, @OXY2DEV): Add features to grammar. + +Author: @OXY2DEV +]] +local a = 1; From a10d8d663f12e390fb165d6603e6f5f558f907f8 Mon Sep 17 00:00:00 2001 From: Shawon Date: Mon, 12 Jan 2026 00:03:45 +0600 Subject: [PATCH 28/31] chore: Cleaned up some codes --- lua/markview/parsers/comment.lua | 159 +++++++++++++++++++++++++++---- 1 file changed, 142 insertions(+), 17 deletions(-) diff --git a/lua/markview/parsers/comment.lua b/lua/markview/parsers/comment.lua index 4f654dc..053df4a 100644 --- a/lua/markview/parsers/comment.lua +++ b/lua/markview/parsers/comment.lua @@ -6,10 +6,11 @@ local comment = {}; comment.content = {}; --- Queried contents, but sorted ----@type { [string]: table } +---@type markview.parsed.comment_sorted +---@diagnostic disable-next-line: missing-fields comment.sorted = {} ---- Wrapper for `table.insert()`. +--[[ Wrapper for `table.insert()`. ]] ---@param data table comment.insert = function (data) table.insert(comment.content, data); @@ -21,12 +22,20 @@ comment.insert = function (data) table.insert(comment.sorted[data.class], data); end ---- Tasks. +--[[ +Conventional commit style tasks. + +```comment +feat: Added comment parser. +``` +]] ---@param buffer integer ---@param TSNode TSNode ---@param text string[] ---@param range markview.parsed.comment.tasks.range comment.task = function (buffer, TSNode, text, range) + ---|fS + local kind = TSNode:field("type")[1]; for child in TSNode:iter_children() do @@ -48,14 +57,24 @@ comment.task = function (buffer, TSNode, text, range) text = text, range = range, }); + + ---|fE end ---- Tasks(legacy parser). +--[[ +Conventional commit style tasks(for the original parser). + +```comment +feat: Added comment parser. +``` +]] ---@param buffer integer ---@param TSNode TSNode ---@param text string[] ---@param range markview.parsed.comment.tasks.range comment.tag = function (buffer, TSNode, text, range) + ---|fS + local kind; for child in TSNode:iter_children() do @@ -87,14 +106,24 @@ comment.tag = function (buffer, TSNode, text, range) text = text, range = range, }); + + ---|fE end ---- Tasks scope parser(legacy parser). +--[[ +Conventional commit style task scope(for the original parser). + +```comment +feat(scope): Added comment parser. +``` +]] ---@param buffer integer ---@param _ TSNode ---@param text string[] ---@param root_range markview.parsed.comment.tasks.range comment.tag_scope = function (buffer, _, text, root_range) + ---|fS + local lpeg = vim.lpeg; local function as_wspace (m) return { kind = "space", value = m }; end @@ -120,6 +149,16 @@ comment.tag_scope = function (buffer, _, text, root_range) local desc_issue = lpeg.C( issue_name * lpeg.P("#") * ( lpeg.R("09") ^ 1 ) ) / as_issue; local token = space + comma + desc_issue + num_issue + mention + word; + + --[[ + A scope may contain one or more `token`s separated by `,` & *whitespaces*. + + Valid tokens may be any of, + + - Mentions(`@foo`). + - Issue reference(`#48`, `OXY2DEV/markview.nvim#48`). + - Keyword(must start with a letter). + ]] local scope = lpeg.Ct(token^0); local col_start = root_range[2]; @@ -153,45 +192,62 @@ comment.tag_scope = function (buffer, _, text, root_range) col_start = col_start + #item.value; end + + ---|fE end ---- Issue. +--[[ +Conventional commit style task scope. + +```comment +feat(scope): Added comment parser. +``` +]] ---@param text string[] ---@param range markview.parsed.range comment.task_scope = function (_, _, text, range) + ---|fS + comment.insert({ class = "comment_task_scope", text = text, range = range, }); + + ---|fE end ---- Issue. ---@param text string[] ---@param range markview.parsed.range comment.bold = function (_, _, text, range) + ---|fS + comment.insert({ class = "comment_bold", text = text, range = range, }); + + ---|fE end ---- Issue. ---@param text string[] ---@param range markview.parsed.range comment.italic = function (_, _, text, range) + ---|fS + comment.insert({ class = "comment_italic", text = text, range = range, }); + + ---|fE end ---- Issue. ---@param text string[] ---@param range markview.parsed.range comment.inline_code = function (_, _, text, range) @@ -203,12 +259,20 @@ comment.inline_code = function (_, _, text, range) }); end --- Issue. +--[[ +Markdown-style fenced code blocks. + +```lua +vim.print("Hello, Neovim!"); +``` +]] ---@param buffer integer ---@param TSNode TSNode ---@param text string[] ---@param range markview.parsed.comment.code_blocks.range comment.code_block = function (buffer, TSNode, text, range) + ---|fS + local uses_tab = false; local lang = TSNode:field("language")[1]; @@ -259,36 +323,72 @@ comment.code_block = function (buffer, TSNode, text, range) text = text, range = range, }); + + ---|fE end ---- Issue. +--[[ +Issue reference. + +It may be of any of the following format(s), + +- Numeric(`#99`). +- Descriptive(`owner/repo#99`). + +```comment +OXY2DEV/markview.nvim#48 +#48 +``` +]] ---@param text string[] ---@param range markview.parsed.range comment.issue = function (_, _, text, range) + ---|fS + comment.insert({ class = "comment_issue", text = text, range = range, }); + + ---|fE end ---- Issue. +--[[ +User handle mention. + +```comment +See, @username +``` +]] ---@param text string[] ---@param range markview.parsed.range comment.mention = function (_, _, text, range) + ---|fS + comment.insert({ class = "comment_mention", text = text, range = range, }); + + ---|fE end ---- Issue. +--[[ +URL. + +```comment +www.example.com +``` +]] ---@param text string[] ---@param range markview.parsed.range comment.url = function (_, _, text, range) + ---|fS + comment.insert({ class = "comment_url", destination = text[1] or "", @@ -296,12 +396,22 @@ comment.url = function (_, _, text, range) text = text, range = range, }); + + ---|fE end ---- Issue. +--[[ +Markdown-like autolinks. + +```comment +Mail to +``` +]] ---@param text string[] ---@param range markview.parsed.range comment.autolink = function (_, _, text, range) + ---|fS + comment.insert({ class = "comment_autolink", destination = string.gsub(text[1] or "", "^%<", ""):gsub("%>$", ""), @@ -309,21 +419,32 @@ comment.autolink = function (_, _, text, range) text = text, range = range, }); + + ---|fE end ---- Issue. +--[[ +Vimdoc-like help tag links. + +```comment +See |intro.txt| +``` +]] ---@param text string[] ---@param range markview.parsed.range comment.taglink = function (_, _, text, range) + ---|fS + comment.insert({ class = "comment_taglink", text = text, range = range, }); + + ---|fE end ---- Comment parser ---@param buffer integer ---@param TSTree table ---@param from integer? @@ -331,7 +452,9 @@ end ---@return markview.parsed.comment[] ---@return markview.parsed.comment_sorted comment.parse = function (buffer, TSTree, from, to) - -- Clear the previous contents + ---|fS + + ---@diagnostic disable-next-line: missing-fields comment.sorted = {}; comment.content = {}; @@ -421,6 +544,8 @@ comment.parse = function (buffer, TSTree, from, to) end return comment.content, comment.sorted; + + ---|fE end return comment; From 28f4f3428d29d2f92acfb23bc041ffc40131d4f2 Mon Sep 17 00:00:00 2001 From: Shawon Date: Mon, 12 Jan 2026 00:23:00 +0600 Subject: [PATCH 29/31] doc: Added help files --- doc/markview.nvim-comment.txt | 1197 ++++++++++++++++++++++++++++ doc/markview.nvim-experimental.txt | 6 + doc/markview.nvim-integrations.txt | 21 + doc/markview.nvim-preview.txt | 1 + doc/tags | 13 + 5 files changed, 1238 insertions(+) create mode 100644 doc/markview.nvim-comment.txt diff --git a/doc/markview.nvim-comment.txt b/doc/markview.nvim-comment.txt new file mode 100644 index 0000000..df8de5e --- /dev/null +++ b/doc/markview.nvim-comment.txt @@ -0,0 +1,1197 @@ +*markview.nvim-comment* 🧩 HTML options for `markview` + +demo {img:1} + +>lua + --[[ Configuration for `comments`. ]] + ---@class markview.config.comment + --- + ---@field enable boolean Enable **comment** rendering. + --- + ---@field autolinks markview.config.comment.autolinks + ---@field code_blocks markview.config.comment.code_blocks + ---@field inline_codes markview.config.comment.inline_codes + ---@field issues markview.config.comment.issues + ---@field mentions markview.config.comment.mentions + ---@field taglinks markview.config.comment.taglinks + ---@field tasks markview.config.comment.tasks + ---@field task_scopes markview.config.comment.task_scopes + ---@field urls markview.config.comment.urls +< + +▋  Warning +▋ Fancy comments are experimental at the moment. Single line comments like +▋ these, +▋ +>lua + -- feat: Some comment +< + +▋ May not be correctly rendered when in large groups. Use multi-line +▋ comments(e.g. `--[[ ... ]]`, `/* ... */`) for these. +▋ This is a Neovim issue with tree-sitter injections in general and not a plugin +▋ issue! + +-------------------------------------------------------------------------------- +enable *markview.nvim-comment.enable* + +>lua + enable = true +< + +Enable rendering of fancy comments. + +-------------------------------------------------------------------------------- +autolinks *markview.nvim-comment.autolinks* + +>lua + --- Configuration for autolinks. + ---@class markview.config.comment.autolinks + --- + ---@field enable boolean Enable rendering of ``s. + --- + ---@field default markview.config.comments.autolinks.opts Default configuration. + ---@field [string] markview.config.comments.autolinks.opts Configuration for autolinks matching the key's pattern. +< + +Enable rendering of ``. + +See default ~ +configuration ~ + +>lua + autolinks = { + enable = true, + + default = { + icon = "󰋽 ", + hl = "MarkviewPalette6", + }, + + ---|fS + + --NOTE(@OXY2DEV): Github sites. + + ["github%.com/[%a%d%-%_%.]+%/?$"] = { + --- github.com/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/?$"] = { + --- github.com// + icon = "󰳐 ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/tree/[%a%d%-%_%.]+%/?$"] = { + --- github.com///tree/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + local repo, branch = string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)/tree/([%a%d%-%_%.]+)%/?$"); + return repo .. " at " .. branch; + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+%/?$"] = { + --- github.com///commits/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+)%/?$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/releases$"] = { + --- github.com///releases + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Releases • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/releases$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/tags$"] = { + --- github.com///tags + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Tags • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/tags$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/issues$"] = { + --- github.com///issues + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Issues • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/issues$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/pulls$"] = { + --- github.com///pulls + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Pull requests • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/pulls$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/wiki$"] = { + --- github.com///wiki + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Wiki • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/wiki$"); + end + }, + + --- NOTE(@OXY2DEV): Commonly used sites by programmers. + + ["developer%.mozilla%.org"] = { + priority = -9999, + + icon = "󰖟 ", + hl = "MarkviewPalette5Fg" + }, + + ["w3schools%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette4Fg" + }, + + ["stackoverflow%.com"] = { + priority = -9999, + + icon = "󰓌 ", + hl = "MarkviewPalette2Fg" + }, + + ["reddit%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["github%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["gitlab%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["dev%.to"] = { + priority = -9999, + + icon = "󱁴 ", + hl = "MarkviewPalette0Fg" + }, + + ["codepen%.io"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["replit%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["jsfiddle%.net"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette5Fg" + }, + + ["npmjs%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette0Fg" + }, + + ["pypi%.org"] = { + priority = -9999, + + icon = "󰆦 ", + hl = "MarkviewPalette0Fg" + }, + + ["mvnrepository%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette1Fg" + }, + + ["medium%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["linkedin%.com"] = { + priority = -9999, + + icon = "󰌻 ", + hl = "MarkviewPalette5Fg" + }, + + ["news%.ycombinator%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["neovim%.io/doc/user/.*#%_?.*$"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file, tag = string.match(item.destination, "neovim%.io/doc/user/(.*)#%_?(.*)$"); + --- The actual website seems to show + --- _ in the site name so, we won't + --- be replacing `_`s with ` `s. + file = string.gsub(file, "%.html$", ""); + + return string.format("%s(%s) - Neovim docs", normalize_str(file), tag); + end + }, + ["neovim%.io/doc/user/.*$"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file = string.match(item.destination, "neovim%.io/doc/user/(.*)$"); + file = string.gsub(file, "%.html$", ""); + + return string.format("%s - Neovim docs", normalize_str(file)); + end + }, + + ["github%.com/vim/vim"] = { + priority = -100, + + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["github%.com/neovim/neovim"] = { + priority = -100, + + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["vim%.org"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["luals%.github%.io/wiki/?.*$"] = { + icon = " ", + hl = "MarkviewPalette5Fg", + + text = function (_, item) + if string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$") then + local page_mappings = { + annotations = { + ["as"] = "@as", + ["alias"] = "@alias", + ["async"] = "@async", + ["cast"] = "@cast", + ["class"] = "@class", + ["deprecated"] = "@deprecated", + ["diagnostic"] = "@diagnostic", + ["enum"] = "@enum", + ["field"] = "@field", + ["generic"] = "@generic", + ["meta"] = "@meta", + ["module"] = "@module", + ["nodiscard"] = "@nodiscard", + ["operator"] = "@operator", + ["overload"] = "@overload", + ["package"] = "@package", + ["param"] = "@param", + ["see"] = "@see", + ["source"] = "@source", + ["type"] = "@type", + ["vaarg"] = "@vaarg", + ["version"] = "@version" + } + }; + + local page, section = string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$"); + + if page_mappings[page] and page_mappings[page][section] then + section = page_mappings[page][section]; + else + section = normalize_str(string.gsub(section, "%-", " ")); + end + + return string.format("%s(%s) | Lua Language Server", normalize_str(page), section); + elseif string.match(item.destination, "") then + local page = string.match(item.destination, "luals%.github%.io/wiki/(.-)/?$"); + + return string.format("%s | Lua Language Server", normalize_str(page)); + else + return item.destination; + end + end + }, + + ---|fE + }, +< + +Each autolink type has the following options. + +>lua + ---@class markview.config.comments.autolinks.opts + --- + ---@field corner_left? string Left corner. + ---@field corner_left_hl? string Highlight group for the left corner. + --- + ---@field padding_left? string Left padding(added after `corner_left`). + ---@field padding_left_hl? string Highlight group for the left padding. + --- + ---@field icon? string Icon(added after `padding_left`). + ---@field icon_hl? string Highlight group for the icon. + --- + --[[ Text to show instead of the `autolink`.]] + ---@field text? + ---| string + ---| function(buffer: integer, item: markview.parsed.comment.autolinks): string + ---@field text_hl? string Highlight group for the shown text. + --- + ---@field hl? string Default highlight group(used by `*_hl` options when they are not set). + --- + ---@field padding_right? string Right padding. + ---@field padding_right_hl? string Highlight group for the right padding. + --- + ---@field corner_right? string Right corner(added after `padding_right`). + ---@field corner_right_hl? string Highlight group for the right corner. +< + +-------------------------------------------------------------------------------- +code_blocks *markview.nvim-comment.code_blocks* + +>lua + --- Configuration for autolinks. + ---@class markview.config.comment.autolinks + --- + ---@field enable boolean Enable rendering of ``s. + --- + ---@field default markview.config.comments.autolinks.opts Default configuration. + ---@field [string] markview.config.comments.autolinks.opts Configuration for autolinks matching the key's pattern. +< + +Enable rendering of `fenced code blocks`. + +See default ~ +configuration ~ + +>lua + code_blocks = { + enable = true, + + border_hl = "MarkviewCode", + info_hl = "MarkviewCodeInfo", + + label_direction = "right", + label_hl = nil, + + min_width = 60, + pad_amount = 2, + pad_char = " ", + + default = { + block_hl = "MarkviewCode", + pad_hl = "MarkviewCode" + }, + + ["diff"] = { + block_hl = function (_, line) + if line:match("^%+") then + return "MarkviewPalette4"; + elseif line:match("^%-") then + return "MarkviewPalette1"; + else + return "MarkviewCode"; + end + end, + pad_hl = "MarkviewCode" + }, + + style = "block", + sign = true, + }, +< + +-------------------------------------------------------------------------------- +inline_codes *markview.nvim-comment.inline_codes* + +>lua + --- Configuration for autolinks. + ---@class markview.config.comment.autolinks + --- + ---@field enable boolean Enable rendering of ``s. + --- + ---@field default markview.config.comments.autolinks.opts Default configuration. + ---@field [string] markview.config.comments.autolinks.opts Configuration for autolinks matching the key's pattern. +< + +Enable rendering of `inline codes`. + +See default ~ +configuration ~ + +>lua + inline_codes = { + padding_left = " ", + padding_right = " ", + + hl = "MarkviewInlineCode", + }, +< + +-------------------------------------------------------------------------------- +issues *markview.nvim-comment.issues* + +>lua + --- Configuration for issues. + ---@class markview.config.comment.issues + --- + ---@field enable boolean Enable rendering of `#issue`s. + --- + ---@field default markview.config.__inline Default configuration for issues. + ---@field [string] markview.config.__inline Configuration for issues whose text matches with the key's pattern. +< + +Enable rendering of `inline codes`. + +See default ~ +configuration ~ + +>lua + issues = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette2", + }, + }, +< + +Each issue type has inline options {1}, unless explicitly mentioned otherwise. + +-------------------------------------------------------------------------------- +mentions *markview.nvim-comment.mentions* + +>lua + --- Configuration for mentions. + ---@class markview.config.comment.mentions + --- + ---@field enable boolean Enable rendering of `@mention`s. + --- + ---@field default markview.config.__inline Default configuration for mentions. + ---@field [string] markview.config.__inline Configuration for mentions whose text matches with the key's pattern. +< + +Enable rendering of `@mentions`. + +See default ~ +configuration ~ + +>lua + mentions = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette5", + }, + }, +< + +Each mention type has inline options {2}, unless explicitly mentioned otherwise. + +-------------------------------------------------------------------------------- +taglinks *markview.nvim-comment.taglinks* + +>lua + --- Configuration for taglinks. + ---@class markview.config.comment.taglinks + --- + ---@field enable boolean Enable rendering of `|taglink|`s. + --- + ---@field default markview.config.__inline Default configuration. + ---@field [string] markview.config.__inline Configuration for taglinks matching the key's pattern. +< + +Enable rendering of `|taglinks|`. + +See default ~ +configuration ~ + +>lua + taglinks = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = "󰌷 ", + + hl = "MarkviewHyperlink", + }, + }, +< + +Each taglink type has inline options {3}, unless explicitly mentioned otherwise. + +-------------------------------------------------------------------------------- +tasks *markview.nvim-comment.tasks* + +>lua + ---@class markview.config.comment.tasks + --- + ---@field enable boolean + --- + ---@field default markview.config.comment.tasks.opts + ---@field [string] markview.config.comment.tasks.opts +< + +Enable rendering of `tasks`. + +See default ~ +configuration ~ + +>lua + tasks = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = "󰄰 ", + + hl = "MarkviewPalette1", + }, + + ["^feat"] = { + padding_left = " ", + padding_right = " ", + + icon = "󱕅 ", + + hl = "MarkviewPalette7", + }, + + praise = { + padding_left = " ", + padding_right = " ", + + icon = "󱥋 ", + + hl = "MarkviewPalette3", + }, + + ["^suggest"] = { + padding_left = " ", + padding_right = " ", + + icon = "󰣖 ", + + hl = "MarkviewPalette2", + }, + + thought = { + padding_left = " ", + padding_right = " ", + + icon = "󰧑 ", + + hl = "MarkviewPalette0", + }, + + note = { + padding_left = " ", + padding_right = " ", + + icon = "󰠮 ", + + hl = "MarkviewPalette5", + }, + + ["^info"] = { + padding_left = " ", + padding_right = " ", + + icon = "󰋼 ", + + hl = "MarkviewPalette0", + }, + + xxx = { + padding_left = " ", + padding_right = " ", + + icon = "󰓽 ", + + hl = "MarkviewPalette0", + }, + + ["^nit"] = { + padding_left = " ", + padding_right = " ", + + icon = "󰩰 ", + + hl = "MarkviewPalette6", + }, + + ["^warn"] = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette3", + }, + + fix = { + padding_left = " ", + padding_right = " ", + + icon = "󰁨 ", + + hl = "MarkviewPalette7", + }, + + hack = { + padding_left = " ", + padding_right = " ", + + icon = "󱍔 ", + + hl = "MarkviewPalette1", + }, + + typo = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette0", + }, + + wip = { + padding_left = " ", + padding_right = " ", + + icon = "󰦖 ", + + hl = "MarkviewPalette2", + }, + + issue = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette1", + }, + + ["error"] = { + padding_left = " ", + padding_right = " ", + + icon = "󰅙 ", + + hl = "MarkviewPalette1", + }, + + fixme = { + padding_left = " ", + padding_right = " ", + + icon = "󰶯 ", + + hl = "MarkviewPalette4", + }, + + deprecated = { + padding_left = " ", + padding_right = " ", + + icon = "󰩆 ", + + hl = "MarkviewPalette1", + }, + }, +< + +Each task type has inline options {4}, unless explicitly mentioned otherwise. + +-------------------------------------------------------------------------------- +task_scopes *markview.nvim-comment.task_scopes* + +>lua + --- Configuration for task_scopes. + ---@class markview.config.comment.task_scopes + --- + ---@field enable boolean Enable rendering of `task scope`s. + --- + ---@field default markview.config.__inline Default configuration for mentions. + ---@field [string] markview.config.__inline Configuration for scopes matching the key's pattern. +< + +Enable rendering of `task_scopes`. + +See default ~ +configuration ~ + +>lua + task_scopes = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = "󰈲 ", + + hl = "MarkviewPalette4", + }, + }, +< + +Each task scope type has inline options {5}, unless explicitly mentioned +otherwise. + +-------------------------------------------------------------------------------- +urls *markview.nvim-comment.urls* + +>lua + --- Configuration for URLs. + ---@class markview.config.comment.urls + --- + ---@field enable boolean Enable rendering of `URL`s. + --- + ---@field default markview.config.comments.urls.opts Default configuration for URLs. + ---@field [string] markview.config.comments.urls.opts Configuration for URLs whose text matches with the key's pattern. +< + +Enable rendering of `urls`. + +See default ~ +configuration ~ + +>lua + urls = { + enable = true, + + default = { + icon = "󰌷 ", + + hl = "MarkviewHyperlink", + }, + + ---|fS + + --NOTE(@OXY2DEV): Github sites. + + ["github%.com/[%a%d%-%_%.]+%/?$"] = { + --- github.com/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/?$"] = { + --- github.com// + icon = "󰳐 ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/tree/[%a%d%-%_%.]+%/?$"] = { + --- github.com///tree/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + local repo, branch = string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)/tree/([%a%d%-%_%.]+)%/?$"); + return repo .. " at " .. branch; + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+%/?$"] = { + --- github.com///commits/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+)%/?$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/releases$"] = { + --- github.com///releases + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Releases • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/releases$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/tags$"] = { + --- github.com///tags + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Tags • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/tags$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/issues$"] = { + --- github.com///issues + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Issues • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/issues$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/pulls$"] = { + --- github.com///pulls + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Pull requests • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/pulls$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/wiki$"] = { + --- github.com///wiki + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Wiki • " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/wiki$"); + end + }, + + --- NOTE(@OXY2DEV): Commonly used sites by programmers. + + ["developer%.mozilla%.org"] = { + priority = -9999, + + icon = "󰖟 ", + hl = "MarkviewPalette5Fg" + }, + + ["w3schools%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette4Fg" + }, + + ["stackoverflow%.com"] = { + priority = -9999, + + icon = "󰓌 ", + hl = "MarkviewPalette2Fg" + }, + + ["reddit%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["github%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["gitlab%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["dev%.to"] = { + priority = -9999, + + icon = "󱁴 ", + hl = "MarkviewPalette0Fg" + }, + + ["codepen%.io"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["replit%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["jsfiddle%.net"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette5Fg" + }, + + ["npmjs%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette0Fg" + }, + + ["pypi%.org"] = { + priority = -9999, + + icon = "󰆦 ", + hl = "MarkviewPalette0Fg" + }, + + ["mvnrepository%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette1Fg" + }, + + ["medium%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["linkedin%.com"] = { + priority = -9999, + + icon = "󰌻 ", + hl = "MarkviewPalette5Fg" + }, + + ["news%.ycombinator%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["neovim%.io/doc/user/.*#%_?.*$"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file, tag = string.match(item.destination, "neovim%.io/doc/user/(.*)#%_?(.*)$"); + --- The actual website seems to show + --- _ in the site name so, we won't + --- be replacing `_`s with ` `s. + file = string.gsub(file, "%.html$", ""); + + return string.format("%s(%s) - Neovim docs", normalize_str(file), tag); + end + }, + ["neovim%.io/doc/user/.*$"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file = string.match(item.destination, "neovim%.io/doc/user/(.*)$"); + file = string.gsub(file, "%.html$", ""); + + return string.format("%s - Neovim docs", normalize_str(file)); + end + }, + + ["github%.com/vim/vim"] = { + priority = -100, + + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["github%.com/neovim/neovim"] = { + priority = -100, + + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["vim%.org"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["luals%.github%.io/wiki/?.*$"] = { + icon = " ", + hl = "MarkviewPalette5Fg", + + text = function (_, item) + if string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$") then + local page_mappings = { + annotations = { + ["as"] = "@as", + ["alias"] = "@alias", + ["async"] = "@async", + ["cast"] = "@cast", + ["class"] = "@class", + ["deprecated"] = "@deprecated", + ["diagnostic"] = "@diagnostic", + ["enum"] = "@enum", + ["field"] = "@field", + ["generic"] = "@generic", + ["meta"] = "@meta", + ["module"] = "@module", + ["nodiscard"] = "@nodiscard", + ["operator"] = "@operator", + ["overload"] = "@overload", + ["package"] = "@package", + ["param"] = "@param", + ["see"] = "@see", + ["source"] = "@source", + ["type"] = "@type", + ["vaarg"] = "@vaarg", + ["version"] = "@version" + } + }; + + local page, section = string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$"); + + if page_mappings[page] and page_mappings[page][section] then + section = page_mappings[page][section]; + else + section = normalize_str(string.gsub(section, "%-", " ")); + end + + return string.format("%s(%s) | Lua Language Server", normalize_str(page), section); + elseif string.match(item.destination, "") then + local page = string.match(item.destination, "luals%.github%.io/wiki/(.-)/?$"); + + return string.format("%s | Lua Language Server", normalize_str(page)); + else + return item.destination; + end + end + }, + + ---|fE + }, +< + +Each URL type has inline options {6}, unless explicitly mentioned otherwise. + + ╶────────────────────────────────────────────────────────────────────────────╴ + +-------------------------------------------------------------------------------- +Inline syntax + +Inline elements support most of these options. + +>lua + ---@class markview.config.__inline + --- + ---@field enable? boolean Only valid if it's a top level option, Used for disabling previews. + ---@field virtual? boolean In `inline_codes`, when `true` masks the text with a virtual text(useful if the line has a background). + --- + ---@field corner_left? string Left corner. + ---@field corner_left_hl? string Highlight group for the left corner. + --- + ---@field padding_left? string Left padding(added after `corner_left`). + ---@field padding_left_hl? string Highlight group for the left padding. + --- + ---@field icon? string Icon(added after `padding_left`). + ---@field icon_hl? string Highlight group for the icon. + --- + ---@field hl? string Default highlight group(used by `*_hl` options when they are not set). + --- + ---@field padding_right? string Right padding. + ---@field padding_right_hl? string Highlight group for the right padding. + --- + ---@field corner_right? string Right corner(added after `padding_right`). + ---@field corner_right_hl? string Highlight group for the right corner. + --- + --- + --- + ---@field block_hl? string Only for `block_references`, highlight group for the block name. + ---@field file_hl? string Only for `block_references`, highlight group for the file name. +< + +Links ~ + +1: #inline-syntax +2: #inline-syntax +3: #inline-syntax +4: #inline-syntax +5: #inline-syntax +6: #inline-syntax + +Images ~ + +1: ./images/comment/markview.nvim-comment.injection.png + +vim:ft=help:textwidth=80:tabstop=4:noexpandtab: diff --git a/doc/markview.nvim-experimental.txt b/doc/markview.nvim-experimental.txt index 65a0e3f..ed7937d 100644 --- a/doc/markview.nvim-experimental.txt +++ b/doc/markview.nvim-experimental.txt @@ -19,6 +19,12 @@ ---@field linewise_ignore_org_indent? boolean Prevents indentation of sections from being cleared in `linewise_hybrid_mode`. < +-------------------------------------------------------------------------------- +fancy_comments *markview.nvim-experimental.fancy_comments* + +When true enables `fancy comment rendering`. See [integrations#fancy_comments]() +for more information. + -------------------------------------------------------------------------------- date_formats *markview.nvim-experimental.date_formats* diff --git a/doc/markview.nvim-integrations.txt b/doc/markview.nvim-integrations.txt index bdc6f90..a21d3b6 100644 --- a/doc/markview.nvim-integrations.txt +++ b/doc/markview.nvim-integrations.txt @@ -113,6 +113,23 @@ You can use `markview.nvim` to prettify the LSP hover window. You can see an example here {6}. +-------------------------------------------------------------------------------- +📦 Fancy comments *markview.nvim-integrations.nvim-fancy_comments* + +▋  Attention +▋ This will remap `gx` by default! Set preview.map_gx {7} to `false` to +▋ overwrite this behavior. + +Conventional commit style commits can be rendered by `markview.nvim`. + +Demo {img:2} + +For this you would need a `comment` parser. You can use either, + +◆ stsewd/tree-sitter-comment {8}, which supports some simple syntax. +◆ OXY2DEV/tree-sitter-comment {9}, which also supports a subset of `markdown` & + `vimdoc`. See [installation](). + Links ~ 1: https://github.com/OXY2DEV/markview.nvim/wiki/Integrations @@ -121,9 +138,13 @@ Links ~ 4: `markview.nvim-markdown.headings` 5: `markview.nvim-markdown.list_items` 6: https://gist.github.com/OXY2DEV/645c90df32095a8a397735d0be646452 +7: `markview.nvim-preview.map_gx` +8: https://github.com/stsewd/tree-sitter-comment +9: https://github.com/OXY2DEV/tree-sitter-comment Images ~ 1: ./images/markview.nvim-lsp_hover.png +2: ./images/comments/markview.nvim-comment.png vim:ft=help:textwidth=80:tabstop=4:noexpandtab: diff --git a/doc/markview.nvim-preview.txt b/doc/markview.nvim-preview.txt index a22a750..617bd93 100644 --- a/doc/markview.nvim-preview.txt +++ b/doc/markview.nvim-preview.txt @@ -160,6 +160,7 @@ raw_previews *markview.nvim-preview.raw_previews* --- in `hybrid mode`. ---@class markview.config.preview.raw --- + ---@field comment? markview.config.preview.raw.comment[] ---@field html? markview.config.preview.raw.html[] ---@field latex? markview.config.preview.raw.latex[] ---@field markdown? markview.config.preview.raw.markdown[] diff --git a/doc/tags b/doc/tags index fad81fd..959bcad 100644 --- a/doc/tags +++ b/doc/tags @@ -3,12 +3,24 @@ markview.nvim markview.nvim.txt /*markview.nvim* markview.nvim-advanced markview.nvim-advanced.txt /*markview.nvim-advanced* markview.nvim-autocmds markview.nvim-autocmds.txt /*markview.nvim-autocmds* markview.nvim-commands markview.nvim.txt /*markview.nvim-commands* +markview.nvim-comment markview.nvim-comment.txt /*markview.nvim-comment* +markview.nvim-comment.autolinks markview.nvim-comment.txt /*markview.nvim-comment.autolinks* +markview.nvim-comment.code_blocks markview.nvim-comment.txt /*markview.nvim-comment.code_blocks* +markview.nvim-comment.enable markview.nvim-comment.txt /*markview.nvim-comment.enable* +markview.nvim-comment.inline_codes markview.nvim-comment.txt /*markview.nvim-comment.inline_codes* +markview.nvim-comment.issues markview.nvim-comment.txt /*markview.nvim-comment.issues* +markview.nvim-comment.mentions markview.nvim-comment.txt /*markview.nvim-comment.mentions* +markview.nvim-comment.taglinks markview.nvim-comment.txt /*markview.nvim-comment.taglinks* +markview.nvim-comment.task_scopes markview.nvim-comment.txt /*markview.nvim-comment.task_scopes* +markview.nvim-comment.tasks markview.nvim-comment.txt /*markview.nvim-comment.tasks* +markview.nvim-comment.urls markview.nvim-comment.txt /*markview.nvim-comment.urls* markview.nvim-config markview.nvim-config.txt /*markview.nvim-config* markview.nvim-contribute markview.nvim.txt /*markview.nvim-contribute* markview.nvim-dev.txt markview.nvim-dev.txt /*markview.nvim-dev.txt* markview.nvim-experimental markview.nvim-experimental.txt /*markview.nvim-experimental* markview.nvim-experimental.date_formats markview.nvim-experimental.txt /*markview.nvim-experimental.date_formats* markview.nvim-experimental.date_time_formats markview.nvim-experimental.txt /*markview.nvim-experimental.date_time_formats* +markview.nvim-experimental.fancy_comments markview.nvim-experimental.txt /*markview.nvim-experimental.fancy_comments* markview.nvim-experimental.file_open_command markview.nvim-experimental.txt /*markview.nvim-experimental.file_open_command* markview.nvim-experimental.linewise_ignore_org_indent markview.nvim-experimental.txt /*markview.nvim-experimental.linewise_ignore_org_indent* markview.nvim-experimental.list_empty_line_tolerance markview.nvim-experimental.txt /*markview.nvim-experimental.list_empty_line_tolerance* @@ -30,6 +42,7 @@ markview.nvim-integrations.blink-cmp markview.nvim-integrations.txt /*markview.n markview.nvim-integrations.color_blending markview.nvim-integrations.txt /*markview.nvim-integrations.color_blending* markview.nvim-integrations.gx markview.nvim-integrations.txt /*markview.nvim-integrations.gx* markview.nvim-integrations.nowrap markview.nvim-integrations.txt /*markview.nvim-integrations.nowrap* +markview.nvim-integrations.nvim-fancy_comments markview.nvim-integrations.txt /*markview.nvim-integrations.nvim-fancy_comments* markview.nvim-integrations.transparent_colorschemes markview.nvim-integrations.txt /*markview.nvim-integrations.transparent_colorschemes* markview.nvim-integrations.wrap markview.nvim-integrations.txt /*markview.nvim-integrations.wrap* markview.nvim-latex markview.nvim-latex.txt /*markview.nvim-latex* From 0f4e97d3b83971cc8fe1a02dcc8e935756a37eb3 Mon Sep 17 00:00:00 2001 From: Shawon Date: Mon, 12 Jan 2026 00:37:41 +0600 Subject: [PATCH 30/31] doc: Updated README.md --- README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/README.md b/README.md index 59bd961..c07afa7 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@
+
@@ -80,6 +81,7 @@ Core features, + Highly customisable! You can change almost anything using the config! + Dynamic `highlight groups` that automatically updates with the colorscheme! + `Callout`, `checkbox` completions for `blink.cmp` & `nvim-cmp`. ++ Works with `tree-sitter injections` too! @@ -104,6 +106,32 @@ Also see, Expand to see complete feature list +#### Fancy comments, + + + +> Comments are still experimental! The original parser only supports basic features. + +Conventional commit style comments with support for a subset of `markdown` & `vimdoc`. See [integrations#fancy-comments](https://github.com/OXY2DEV/markview.nvim/wiki/Integrations#-fancy-comments) For more info. + +Supported syntax, + ++ Tasks(e.g. `feat`, `TODO` etc.) ++ Task scopes. + +Extra syntax(needs external parser), + ++ `**Bold**` ++ `*Italic*` ++ `Code` ++ `'Quoted_text'` ++ `"Double quoted text"` ++ `@mentions` ++ `issues/reference#52` ++ `https://example.com` ++ `|help-section|` ++ Code blocks + #### HTML, @@ -372,6 +400,7 @@ Parsers, - `markdown` - `markdown_inline` +- `comment`(optional) - `html`(optional) - `latex`(optional) - `typst`(optional) From 658f9b118c8b8941cc9e84626125f27a6898f305 Mon Sep 17 00:00:00 2001 From: Shawon Date: Mon, 12 Jan 2026 00:40:21 +0600 Subject: [PATCH 31/31] doc: Updated help files --- doc/markview.nvim.txt | 95 +++++++++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 31 deletions(-) diff --git a/doc/markview.nvim.txt b/doc/markview.nvim.txt index 4317ad2..cf7508e 100644 --- a/doc/markview.nvim.txt +++ b/doc/markview.nvim.txt @@ -8,7 +8,7 @@ │ wrap {img:2} │ nowrap {img:3} │ ╰─────────────────┴──────────────────╯ - Image {img:5} Image {img:4} + Image {img:6} Image {img:5} Image {img:4} 📚 Wiki {3} | 🧩 Extras {2} | 📦 Presets {1} @@ -26,6 +26,7 @@ Core features, ◇ Highly customisable! You can change almost anything using the config! ◇ Dynamic `highlight groups` that automatically updates with the colorscheme! ◇ `Callout`, `checkbox` completions for `blink.cmp` & `nvim-cmp`. +◇ Works with `tree-sitter injections` too! -------------------------------------------------------------------------------- Table of contents @@ -37,9 +38,37 @@ Table of contents 🧩 Extras ............................................... |markview.nvim-extras| 📦 Presets ............................................. |markview.nvim-presets| +Fancy comments, ~ + +Image {img:7} + +▋ Comments are still experimental! The original parser only supports basic +▋ features. + +Conventional commit style comments with support for a subset of `markdown` & +`vimdoc`. See integrations#fancy-comments {6} For more info. + +Supported syntax, + +◇ Tasks(e.g. `feat`, `TODO` etc.) +◇ Task scopes. + +Extra syntax(needs external parser), + +◇ `**Bold**` +◇ `*Italic*` +◇ `Code` +◇ `'Quoted_text'` +◇ `"Double quoted text"` +◇ `@mentions` +◇ `issues/reference#52` +◇ `https://example.com` +◇ `|help-section|` +◇ Code blocks + HTML, ~ -Image {img:6} +Image {img:8} ◇ Customizable previews for `container` & `void` elements. ◇ Supports the following container elements out of the box, @@ -63,7 +92,7 @@ Image {img:6} LaTeX, ~ -Image {img:7} +Image {img:9} ◇ Supports basic LaTeX syntax, ◇ Math blocks(typically `$$...$$`) & inline math(typically `$...$`). @@ -133,7 +162,7 @@ Image {img:7} Markdown, ~ -Image {img:8} +Image {img:10} ◇ Supports basic markdown(Github-flavored) syntax, ◇ Block quotes(with support for `callouts` & titles). @@ -162,7 +191,7 @@ Image {img:8} ◇ `Org-mode` like indentation for headings. -Image {img:9} +Image {img:11} ◇ Obsidian/PKM extended syntax support, ◇ Block reference links. @@ -178,7 +207,7 @@ Image {img:9} Typst, ~ -Image {img:10} +Image {img:12} ◇ Supports the following items, ◇ Code blocks. @@ -206,7 +235,7 @@ Image {img:10} YAML, ~ -Image {img:11} +Image {img:13} ◇ Custom property icons. ◇ Custom property scope decorations. @@ -229,8 +258,8 @@ Hybrid mode ~ ╭──────────────────────┬──────────────────────╮ │ Normal hybrid mode │ Linewise hybrid mode │ ├──────────────────────┼──────────────────────┤ -│ hybrid_mode {img:12} │ linewise_hybrid_mode │ -│ │ {img:13} │ +│ hybrid_mode {img:14} │ linewise_hybrid_mode │ +│ │ {img:15} │ ╰──────────────────────┴──────────────────────╯ ◇ Node-based edit range(default). @@ -254,7 +283,7 @@ Internal Icon provider features, ◇ 708 different filetype configuration. ◇ Dynamic highlight groups for matching the colorscheme. -Image {img:14} +Image {img:16} ◇ You can use `:Markview traceShow` to see what the plugin has been doing(including how long some of them took). @@ -290,8 +319,8 @@ External icon providers, } < -◆ mini.icons {6} -◆ nvim-web-devicons {7} +◆ mini.icons {7} +◆ nvim-web-devicons {8} Parsers, @@ -308,6 +337,7 @@ Parsers, ◆ `markdown` ◆ `markdown_inline` +◆ `comment`(optional) ◆ `html`(optional) ◆ `latex`(optional) ◆ `typst`(optional) @@ -340,7 +370,7 @@ Add this to your plugin list. ▋ 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. See integrations.transparent_colorschemes {8} if you +highlight groups are used. See integrations.transparent_colorschemes {9} if you use a transparent colorscheme and the colors don't look right. >lua @@ -389,7 +419,7 @@ use a transparent colorscheme and the colors don't look right. 📥 GitHub release ~ -Tagged releases can be found in the release page {9}. +Tagged releases can be found in the release page {10}. ▋ 󰋽 Note ▋ `Github releases` may sometimes be slightly behind `main`. @@ -409,7 +439,7 @@ Tagged releases can be found in the release page {9}. -------------------------------------------------------------------------------- 🧭 Usage -You can find more usage recipes here {10}. +You can find more usage recipes here {11}. -------------------------------------------------------------------------------- 🎇 Commands *markview.nvim-commands* @@ -553,27 +583,30 @@ Links ~ 3: https://github.com/OXY2DEV/markview.nvim/wiki/Home 4: https://github.com/OXY2DEV/markview.nvim/wiki/Integrations#-nowrap 5: https://github.com/OXY2DEV/markview.nvim/wiki/Integrations#-wrap -6: https://github.com/nvim-mini/mini.icons -7: https://github.com/nvim-tree/nvim-web-devicons -8: https://github.com/OXY2DEV/markview.nvim/wiki/Integrations#-transparent-colorschemes -9: https://github.com/OXY2DEV/markview.nvim/releases -10: |markview.nvim-usage| +6: https://github.com/OXY2DEV/markview.nvim/wiki/Integrations#-fancy-comments +7: https://github.com/nvim-mini/mini.icons +8: https://github.com/nvim-tree/nvim-web-devicons +9: https://github.com/OXY2DEV/markview.nvim/wiki/Integrations#-transparent-colorschemes +10: https://github.com/OXY2DEV/markview.nvim/releases +11: |markview.nvim-usage| Images ~ 1: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-splitview.png 2: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-wrap.png 3: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-nowrap.png -4: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-hybrid_mode.png -5: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-splitview_2.png -6: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/html-tokyonight_night.png -7: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/latex-cyberdream.png -8: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/markdown-catppuccin_mocha.png -9: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/markdown_inline-nightfly.png -10: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/typst-kanagawa_wave.png -11: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/yaml-material_palenight.png -12: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/wiki/hybrid_mode.png -13: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/wiki/linewise_hybrid_mode.png -14: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/traceback.png +4: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-comment.png +5: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-hybrid_mode.png +6: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-splitview_2.png +7: https://github.com/OXY2DEV/markview.nvim/wiki/images/comment/markview.nvim-comment.injection.png +8: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/html-tokyonight_night.png +9: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/latex-cyberdream.png +10: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/markdown-catppuccin_mocha.png +11: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/markdown_inline-nightfly.png +12: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/typst-kanagawa_wave.png +13: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/yaml-material_palenight.png +14: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/wiki/hybrid_mode.png +15: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/wiki/linewise_hybrid_mode.png +16: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/traceback.png vim:ft=help:textwidth=80:tabstop=4:noexpandtab: