Skip to content

Commit 8f5bbbd

Browse files
Add support for custom callouts
# Details After adding custom checkboxes, given how similar the implementations are decided to add custom callouts as well. Uses the same setup / interfaces as checkboxes. Configuration parameter callout -> custom.
1 parent 7065c7d commit 8f5bbbd

File tree

13 files changed

+183
-88
lines changed

13 files changed

+183
-88
lines changed

README.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Plugin to improve viewing Markdown files in Neovim
2727
- Block quotes: replace leading `>` with provided icon
2828
- Tables: replace border characters, does NOT automatically align
2929
- [Callouts](https://github.com/orgs/community/discussions/16925)
30+
- Base set as well as custom ones
3031
- Custom checkbox states, function similar to `callouts`
3132
- `LaTeX` blocks: renders formulas if `latex` parser and `pylatexenc` are installed
3233
- Disable rendering when file is larger than provided value
@@ -186,6 +187,9 @@ require('render-markdown').setup({
186187
important = '󰅾 Important',
187188
warning = '󰀪 Warning',
188189
caution = '󰳦 Caution',
190+
custom = {
191+
bug = { raw = '[!BUG]', rendered = '󰨰 Bug', highlight = 'DiagnosticError' },
192+
},
189193
},
190194
-- Window options to use that change between rendered and raw view
191195
win_options = {
@@ -310,8 +314,8 @@ is used to hide the character.
310314

311315
The checked `[ ]` & unchecked `[x]` are directly replaced with these values.
312316

313-
Additionally `custom` states can be specified, an example of this is provided
314-
with: `todo = { raw = '[-]', rendered = '󰥔 ', highlight = '@markup.raw' }`.
317+
Additionally `custom` states can be specified, an example of this is provided with:
318+
`todo = { raw = '[-]', rendered = '󰥔 ', highlight = '@markup.raw' }`.
315319

316320
This requires neovim >= `0.10.0` since it relies on `inline` extmarks.
317321

@@ -332,6 +336,15 @@ This is a special instance of a `block_quote`.
332336
When the `callout` syntax is used the start, i.e. `[!NOTE]`, is replaced
333337
with this text.
334338

339+
Additionally `custom` callouts can be specified, an example of this is provided with:
340+
`bug = { raw = '[!BUG]', rendered = '󰨰 Bug', highlight = 'DiagnosticError' }`.
341+
342+
The key in the `custom` table is unused. The parts of the value are:
343+
344+
- `raw`: matched against the raw text of a `shortcut_link`
345+
- `rendered`: replaces the `raw` value when rendering
346+
- `highlight`: color used for `rendered` text
347+
335348
## Highlight
336349

337350
Options are all contained in the `highlights` table.

demo/callout.gif

-2.1 KB
Loading

demo/callout.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,8 @@
2828
2929
> [!CAUTION]
3030
> Cautionary tale
31+
32+
# Bug
33+
34+
> [!BUG]
35+
> Custom bug

doc/render-markdown.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Plugin to improve viewing Markdown files in Neovim
5050
- Block quotes: replace leading `>` with provided icon
5151
- Tables: replace border characters, does NOT automatically align
5252
- Callouts <https://github.com/orgs/community/discussions/16925>
53+
- Base set as well as custom ones
5354
- Custom checkbox states, function similar to `callouts`
5455
- `LaTeX` blocks: renders formulas if `latex` parser and `pylatexenc` are installed
5556
- Disable rendering when file is larger than provided value
@@ -218,6 +219,9 @@ Full Default Configuration ~
218219
important = '󰅾 Important',
219220
warning = '󰀪 Warning',
220221
caution = '󰳦 Caution',
222+
custom = {
223+
bug = { raw = '[!BUG]', rendered = '󰨰 Bug', highlight = 'DiagnosticError' },
224+
},
221225
},
222226
-- Window options to use that change between rendered and raw view
223227
win_options = {
@@ -371,6 +375,16 @@ This is a special instance of a `block_quote`.
371375
When the `callout` syntax is used the start, i.e.� `[!NOTE]`, is replaced with
372376
this text.
373377

378+
Additionally `custom` callouts can be specified, an example of this is provided
379+
with: `bug = { raw = '[!BUG]', rendered = '󰨰 Bug', highlight =
380+
'DiagnosticError' }`.
381+
382+
The key in the `custom` table is unused. The parts of the value are:
383+
384+
- `raw`: matched against the raw text of a `shortcut_link`
385+
- `rendered`: replaces the `raw` value when rendering
386+
- `highlight`: color used for `rendered` text
387+
374388

375389
HIGHLIGHT *render-markdown-setup-highlight*
376390

justfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ demo-latex:
2222
just demo "latex" "15" ""
2323

2424
demo-callout:
25-
just demo "callout" "35" ""
25+
just demo "callout" "40" ""
2626

2727
demo file rows content:
2828
rm -f demo/{{file}}.gif

lua/render-markdown/callout.lua

Lines changed: 0 additions & 38 deletions
This file was deleted.

lua/render-markdown/component.lua

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
local state = require('render-markdown.state')
2+
3+
---@class render.md.Component
4+
---@field text string
5+
---@field highlight string
6+
7+
---@class render.md.CalloutInfo
8+
---@field text string
9+
---@field key string
10+
11+
---@type render.md.CalloutInfo[]
12+
local callouts = {
13+
{ text = '[!NOTE]', key = 'note' },
14+
{ text = '[!TIP]', key = 'tip' },
15+
{ text = '[!IMPORTANT]', key = 'important' },
16+
{ text = '[!WARNING]', key = 'warning' },
17+
{ text = '[!CAUTION]', key = 'caution' },
18+
}
19+
20+
local M = {}
21+
22+
---@param value string
23+
---@param comparison 'exact'|'contains'
24+
---@return render.md.Component?
25+
M.callout = function(value, comparison)
26+
---@param text string
27+
---@return boolean
28+
local function matches(text)
29+
if comparison == 'exact' then
30+
return value == text
31+
elseif comparison == 'contains' then
32+
return value:find(text, 1, true) ~= nil
33+
else
34+
error(string.format('Unhandled comparison: %s', comparison))
35+
end
36+
end
37+
for _, callout in ipairs(callouts) do
38+
if matches(callout.text) then
39+
return {
40+
text = state.config.callout[callout.key],
41+
highlight = state.config.highlights.callout[callout.key],
42+
}
43+
end
44+
end
45+
for _, callout in pairs(state.config.callout.custom) do
46+
if matches(callout.raw) then
47+
return { text = callout.rendered, highlight = callout.highlight }
48+
end
49+
end
50+
return nil
51+
end
52+
53+
---@param value string
54+
---@param comparison 'exact'|'starts'
55+
---@return render.md.Component?
56+
M.checkbox = function(value, comparison)
57+
---@param text string
58+
---@return boolean
59+
local function matches(text)
60+
if comparison == 'exact' then
61+
return value == text
62+
elseif comparison == 'starts' then
63+
return vim.startswith(value, text)
64+
else
65+
error(string.format('Unhandled comparison: %s', comparison))
66+
end
67+
end
68+
for _, checkbox in pairs(state.config.checkbox.custom) do
69+
if matches(checkbox.raw) then
70+
return { text = checkbox.rendered, highlight = checkbox.highlight }
71+
end
72+
end
73+
return nil
74+
end
75+
76+
return M

lua/render-markdown/custom_checkbox.lua

Lines changed: 0 additions & 27 deletions
This file was deleted.

lua/render-markdown/handler/markdown.lua

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
local callout = require('render-markdown.callout')
2-
local custom_checkbox = require('render-markdown.custom_checkbox')
1+
local component = require('render-markdown.component')
32
local icons = require('render-markdown.icons')
43
local list = require('render-markdown.list')
54
local logger = require('render-markdown.logger')
@@ -120,9 +119,9 @@ M.render_node = function(namespace, buf, capture, node)
120119
local highlight = highlights.quote
121120
local quote = ts.parent_in_section(node, 'block_quote')
122121
if quote ~= nil then
123-
local key = callout.get_key_contains(vim.treesitter.get_node_text(quote, buf))
124-
if key ~= nil then
125-
highlight = highlights.callout[key]
122+
local callout = component.callout(vim.treesitter.get_node_text(quote, buf), 'contains')
123+
if callout ~= nil then
124+
highlight = callout.highlight
126125
end
127126
end
128127

@@ -260,7 +259,7 @@ M.sibling_checkbox = function(buf, node)
260259
if paragraph == nil then
261260
return false
262261
end
263-
if custom_checkbox.get_starts(vim.treesitter.get_node_text(paragraph, buf)) ~= nil then
262+
if component.checkbox(vim.treesitter.get_node_text(paragraph, buf), 'starts') ~= nil then
264263
return true
265264
end
266265
return false

lua/render-markdown/handler/markdown_inline.lua

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
local callout = require('render-markdown.callout')
2-
local custom_checkbox = require('render-markdown.custom_checkbox')
1+
local component = require('render-markdown.component')
32
local logger = require('render-markdown.logger')
43
local state = require('render-markdown.state')
54
local str = require('render-markdown.str')
@@ -34,9 +33,9 @@ M.render_node = function(namespace, buf, capture, node)
3433
hl_group = highlights.code,
3534
})
3635
elseif capture == 'callout' then
37-
local key = callout.get_key_exact(value)
38-
if key ~= nil then
39-
local callout_text = { state.config.callout[key], highlights.callout[key] }
36+
local callout = component.callout(value, 'exact')
37+
if callout ~= nil then
38+
local callout_text = { callout.text, callout.highlight }
4039
vim.api.nvim_buf_set_extmark(buf, namespace, start_row, start_col, {
4140
end_row = end_row,
4241
end_col = end_col,
@@ -49,12 +48,12 @@ M.render_node = function(namespace, buf, capture, node)
4948
return
5049
end
5150

52-
local checkbox = custom_checkbox.get_exact(value)
51+
local checkbox = component.checkbox(value, 'exact')
5352
if checkbox == nil then
5453
return
5554
end
5655

57-
local checkbox_text = { str.pad_to(value, checkbox.rendered), checkbox.highlight }
56+
local checkbox_text = { str.pad_to(value, checkbox.text), checkbox.highlight }
5857
vim.api.nvim_buf_set_extmark(buf, namespace, start_row, start_col, {
5958
end_row = end_row,
6059
end_col = end_col,

0 commit comments

Comments
 (0)