Skip to content

Commit 0df6719

Browse files
feat: change_events list & link.wiki.body function
## Details This change exposes 2 new configuration options to allow users to show the contents of diagnostics in wiki links as shown in discussion [#228](#228) without using a separate fork that has accrued merge conflicts. This is a modified version of PR [#345](#345) but it offloads the specific details to user configuration. Instead we expose the information needed through a user configurable function and the user can use this to change the body of a wiki link as they please. ### Events The first part is the top level `change_events` configuration which gets joined to the list of default events that trigger re-rendering due to content changes. Since diagnostics changing now impacts the rendered view we need to add the `DiagnosticChanged` event to the list. ```lua require('render-markdown').setup({ change_events = { 'DiagnosticChanged' }, }) ``` Since it's configurable this is only needed for users that want rendering that depends on diagnostics, by default no additional events are added. ### Body Now we use the `link.wiki.body` configuration to dynamically set the main text of a wiki link based on any overlapping diagnostics. This is appended to the icon. If a `nil` return value is provided we fallback to the existing logic with no changes. Below as an implementation specific to the `zk-nvim` plugin, but it is easily modified to match any similar use case: ```lua require('render-markdown').setup({ link = { wiki = { body = function(ctx) local diagnostics = vim.diagnostic.get(ctx.buf, { lnum = ctx.row, severity = vim.diagnostic.severity.HINT, }) for _, diagnostic in ipairs(diagnostics) do if diagnostic.source == 'zk' then return diagnostic.message end end return nil end, }, }, }) ``` Co-authored-by: Michael McDonagh <[email protected]>
1 parent 57fa691 commit 0df6719

File tree

10 files changed

+105
-36
lines changed

10 files changed

+105
-36
lines changed

README.md

+16-2
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ require('render-markdown').setup({
200200
log_runtime = false,
201201
-- Filetypes this plugin will run on
202202
file_types = { 'markdown' },
203+
-- Additional events that will trigger this plugin's render loop
204+
change_events = {},
203205
-- Out of the box language injections for known filetypes that allow markdown to be
204206
-- interpreted in specified locations, see :h treesitter-language-injections
205207
-- Set enabled to false in order to disable
@@ -616,7 +618,13 @@ require('render-markdown').setup({
616618
-- Applies to the inlined icon as a fallback
617619
highlight = 'RenderMarkdownLink',
618620
-- Applies to WikiLink elements
619-
wiki = { icon = '󱗖 ', highlight = 'RenderMarkdownWikiLink' },
621+
wiki = {
622+
icon = '󱗖 ',
623+
body = function()
624+
return nil
625+
end,
626+
highlight = 'RenderMarkdownWikiLink',
627+
},
620628
-- Define custom destination patterns so icons can quickly inform you of what a link
621629
-- contains. Applies to 'inline_link', 'uri_autolink', and wikilink nodes. When multiple
622630
-- patterns match a link the one with the longer pattern is used.
@@ -1246,7 +1254,13 @@ require('render-markdown').setup({
12461254
-- Applies to the inlined icon as a fallback
12471255
highlight = 'RenderMarkdownLink',
12481256
-- Applies to WikiLink elements
1249-
wiki = { icon = '󱗖 ', highlight = 'RenderMarkdownWikiLink' },
1257+
wiki = {
1258+
icon = '󱗖 ',
1259+
body = function()
1260+
return nil
1261+
end,
1262+
highlight = 'RenderMarkdownWikiLink',
1263+
},
12501264
-- Define custom destination patterns so icons can quickly inform you of what a link
12511265
-- contains. Applies to 'inline_link', 'uri_autolink', and wikilink nodes. When multiple
12521266
-- patterns match a link the one with the longer pattern is used.

doc/render-markdown.txt

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*render-markdown.txt* For 0.10.0 Last change: 2025 February 20
1+
*render-markdown.txt* For 0.10.0 Last change: 2025 February 24
22

33
==============================================================================
44
Table of Contents *render-markdown-table-of-contents*
@@ -261,6 +261,8 @@ Default Configuration ~
261261
log_runtime = false,
262262
-- Filetypes this plugin will run on
263263
file_types = { 'markdown' },
264+
-- Additional events that will trigger this plugin's render loop
265+
change_events = {},
264266
-- Out of the box language injections for known filetypes that allow markdown to be
265267
-- interpreted in specified locations, see :h treesitter-language-injections
266268
-- Set enabled to false in order to disable
@@ -677,7 +679,13 @@ Default Configuration ~
677679
-- Applies to the inlined icon as a fallback
678680
highlight = 'RenderMarkdownLink',
679681
-- Applies to WikiLink elements
680-
wiki = { icon = '󱗖 ', highlight = 'RenderMarkdownWikiLink' },
682+
wiki = {
683+
icon = '󱗖 ',
684+
body = function()
685+
return nil
686+
end,
687+
highlight = 'RenderMarkdownWikiLink',
688+
},
681689
-- Define custom destination patterns so icons can quickly inform you of what a link
682690
-- contains. Applies to 'inline_link', 'uri_autolink', and wikilink nodes. When multiple
683691
-- patterns match a link the one with the longer pattern is used.
@@ -1287,7 +1295,13 @@ Link Configuration ~
12871295
-- Applies to the inlined icon as a fallback
12881296
highlight = 'RenderMarkdownLink',
12891297
-- Applies to WikiLink elements
1290-
wiki = { icon = '󱗖 ', highlight = 'RenderMarkdownWikiLink' },
1298+
wiki = {
1299+
icon = '󱗖 ',
1300+
body = function()
1301+
return nil
1302+
end,
1303+
highlight = 'RenderMarkdownWikiLink',
1304+
},
12911305
-- Define custom destination patterns so icons can quickly inform you of what a link
12921306
-- contains. Applies to 'inline_link', 'uri_autolink', and wikilink nodes. When multiple
12931307
-- patterns match a link the one with the longer pattern is used.

lua/render-markdown/core/context.lua

+5
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ function Context:skip(component)
8989
return not util.in_modes(component.render_modes, self.mode)
9090
end
9191

92+
---@return integer
93+
function Context:get_buf()
94+
return self.buf
95+
end
96+
9297
---@param row integer
9398
---@return render.md.CustomCallout?
9499
function Context:get_callout(row)

lua/render-markdown/health.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ local state = require('render-markdown.state')
55
local M = {}
66

77
---@private
8-
M.version = '8.0.6'
8+
M.version = '8.0.7'
99

1010
function M.check()
1111
M.start('version')

lua/render-markdown/init.lua

+18-1
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,16 @@ local M = {}
7272
---@field public icon? string
7373
---@field public highlight? string
7474

75+
---@class (exact) render.md.LinkContext
76+
---@field public buf integer
77+
---@field public row integer
78+
---@field public start_col integer
79+
---@field public end_col integer
80+
---@field public destination string
81+
7582
---@class (exact) render.md.UserWikiLink
7683
---@field public icon? string
84+
---@field public body? fun(ctx: render.md.LinkContext): string?
7785
---@field public highlight? string
7886

7987
---@class (exact) render.md.UserFootnote
@@ -289,6 +297,7 @@ local M = {}
289297
---@field public log_level? render.md.config.LogLevel
290298
---@field public log_runtime? boolean
291299
---@field public file_types? string[]
300+
---@field public change_events? string[]
292301
---@field public injections? table<string, render.md.UserInjection>
293302
---@field public on? render.md.UserCallback
294303
---@field public overrides? render.md.UserConfigOverrides
@@ -322,6 +331,8 @@ M.default_config = {
322331
log_runtime = false,
323332
-- Filetypes this plugin will run on
324333
file_types = { 'markdown' },
334+
-- Additional events that will trigger this plugin's render loop
335+
change_events = {},
325336
-- Out of the box language injections for known filetypes that allow markdown to be
326337
-- interpreted in specified locations, see :h treesitter-language-injections
327338
-- Set enabled to false in order to disable
@@ -738,7 +749,13 @@ M.default_config = {
738749
-- Applies to the inlined icon as a fallback
739750
highlight = 'RenderMarkdownLink',
740751
-- Applies to WikiLink elements
741-
wiki = { icon = '󱗖 ', highlight = 'RenderMarkdownWikiLink' },
752+
wiki = {
753+
icon = '󱗖 ',
754+
body = function()
755+
return nil
756+
end,
757+
highlight = 'RenderMarkdownWikiLink',
758+
},
742759
-- Define custom destination patterns so icons can quickly inform you of what a link
743760
-- contains. Applies to 'inline_link', 'uri_autolink', and wikilink nodes. When multiple
744761
-- patterns match a link the one with the longer pattern is used.

lua/render-markdown/manager.lua

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ function M.attach(buf)
101101

102102
local events = { 'BufWinEnter', 'BufLeave', 'CmdlineChanged', 'CursorHold', 'CursorMoved', 'WinScrolled' }
103103
local change_events = { 'DiffUpdated', 'ModeChanged', 'TextChanged' }
104+
vim.list_extend(change_events, state.change_events)
104105
if config:render('i') then
105106
vim.list_extend(events, { 'CursorHoldI', 'CursorMovedI' })
106107
vim.list_extend(change_events, { 'TextChangedI' })

lua/render-markdown/render/shortcut.lua

+38-24
Original file line numberDiff line numberDiff line change
@@ -98,35 +98,49 @@ function Render:wiki_link()
9898
return
9999
end
100100

101-
local wiki = self.link.wiki
102-
local start_col, end_col = self.node.start_col, self.node.end_col
103-
local values = Str.split(self.node.text:sub(2, -2), '|')
104-
105-
-- Hide opening outer bracket
106-
self:hide(start_col - 1, start_col)
101+
local sections = Str.split(self.node.text:sub(2, -2), '|')
102+
---@type render.md.LinkContext
103+
local ctx = {
104+
buf = self.context:get_buf(),
105+
row = self.node.start_row,
106+
start_col = self.node.start_col - 1,
107+
end_col = self.node.end_col + 1,
108+
destination = sections[1],
109+
}
110+
111+
-- Hide opening & closing outer brackets
112+
self:hide(ctx.start_col, 1)
113+
self:hide(ctx.end_col - 1, 1)
107114

108-
-- Add icon
109-
local icon, highlight = self:from_destination(wiki.icon, wiki.highlight, values[1])
110-
self.marks:add_over('link', self.node, {
111-
virt_text = { { icon, highlight } },
112-
virt_text_pos = 'inline',
113-
})
114-
115-
-- Hide destination if there is an alias
116-
if #values > 1 then
117-
self:hide(start_col + 1, start_col + 1 + #values[1] + 1)
115+
local wiki = self.link.wiki
116+
local icon, highlight = self:from_destination(wiki.icon, wiki.highlight, ctx.destination)
117+
local body = wiki.body(ctx)
118+
if body == nil then
119+
-- Add icon
120+
self.marks:add_over('link', self.node, {
121+
virt_text = { { icon, highlight } },
122+
virt_text_pos = 'inline',
123+
})
124+
-- Hide destination if there is an alias
125+
if #sections > 1 then
126+
self:hide(ctx.start_col + 2, #ctx.destination + 1)
127+
end
128+
else
129+
-- Inline icon & body, hide original text
130+
self.marks:add_over('link', self.node, {
131+
virt_text = { { icon .. body, highlight } },
132+
virt_text_pos = 'inline',
133+
conceal = '',
134+
}, { 0, 1, 0, -1 })
118135
end
119-
120-
-- Hide closing outer bracket
121-
self:hide(end_col, end_col + 1)
122136
end
123137

124138
---@private
125-
---@param start_col integer
126-
---@param end_col integer
127-
function Render:hide(start_col, end_col)
128-
self.marks:add(true, self.node.start_row, start_col, {
129-
end_col = end_col,
139+
---@param col integer
140+
---@param length integer
141+
function Render:hide(col, length)
142+
self.marks:add(true, self.node.start_row, col, {
143+
end_col = col + length,
130144
conceal = '',
131145
})
132146
end

lua/render-markdown/state.lua

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ local configs = {}
1212
---@field enabled boolean
1313
---@field log_runtime boolean
1414
---@field file_types string[]
15+
---@field change_events string[]
1516
---@field on render.md.Callback
1617
---@field custom_handlers table<string, render.md.Handler>
1718
local M = {}
@@ -43,6 +44,7 @@ function M.setup(default_config, user_config)
4344
M.enabled = config.enabled
4445
M.log_runtime = config.log_runtime
4546
M.file_types = config.file_types
47+
M.change_events = config.change_events
4648
M.on = config.on
4749
M.custom_handlers = config.custom_handlers
4850
log.setup(config.log_level)
@@ -259,7 +261,7 @@ function M.validate()
259261
footnote:type('superscript', 'boolean'):type({ 'prefix', 'suffix' }, 'string'):check()
260262
end)
261263
:nested('wiki', function(wiki)
262-
wiki:type({ 'icon', 'highlight' }, 'string'):check()
264+
wiki:type({ 'icon', 'highlight' }, 'string'):type('body', 'function'):check()
263265
end)
264266
:nested('custom', function(patterns)
265267
patterns
@@ -320,7 +322,7 @@ function M.validate()
320322

321323
buffer_rules(validator:spec(M.config, false))
322324
:type('log_runtime', 'boolean')
323-
:list('file_types', 'string')
325+
:list({ 'file_types', 'change_events' }, 'string')
324326
:one_of('preset', { 'none', 'lazy', 'obsidian' })
325327
:one_of('log_level', { 'off', 'debug', 'info', 'error' })
326328
:nested('injections', function(injections)

lua/render-markdown/types.lua

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050

5151
---@class (exact) render.md.WikiLink
5252
---@field public icon string
53+
---@field public body fun(ctx: render.md.LinkContext): string?
5354
---@field public highlight string
5455

5556
---@class (exact) render.md.Footnote
@@ -205,6 +206,7 @@
205206
---@field public log_level render.md.config.LogLevel
206207
---@field public log_runtime boolean
207208
---@field public file_types string[]
209+
---@field public change_events string[]
208210
---@field public injections table<string, render.md.Injection>
209211
---@field public on render.md.Callback
210212
---@field public overrides render.md.ConfigOverrides

scripts/update.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def is_optional(self, field: str) -> bool:
3838
# ---@field public extends? boolean -> extends
3939
# ---@field public start_row integer -> start_row
4040
# ---@field public attach? fun(buf: integer) -> attach
41-
field_name = field.split()[2].replace("?", "")
41+
field_name = field.split()[2].replace("?", "", 1)
4242
return field_name in class_to_optional.get(self.class_name, [])
4343

4444
def validate(self) -> None:
@@ -53,11 +53,11 @@ def to_internal(self) -> str:
5353
lines: list[str] = [self.name.replace("User", "")]
5454
for field in self.fields:
5555
if self.class_name == "UserConfigOverrides":
56-
lines.append(field.replace("?", ""))
56+
lines.append(field.replace("?", "", 1))
5757
elif self.is_optional(field):
5858
lines.append(field)
5959
else:
60-
lines.append(field.replace("User", "").replace("?", ""))
60+
lines.append(field.replace("User", "").replace("?", "", 1))
6161
return "\n".join(lines)
6262

6363
def to_str(self) -> str:

0 commit comments

Comments
 (0)