Skip to content

Commit a1bcbf4

Browse files
feat: add custom title support for callouts
## Details Request: #109 This feature is based off of obsidian's support for changing callout titles: https://help.obsidian.md/Editing+and+formatting/Callouts#Change+the+title When a callout is followed by some text, the text following the callout becomes the title rather than the configured `rendered` value. The icon is still pulled from the `rendered` value and pre-pended to the text. For example something like: `> [!NOTE]` Would result in: `| <NoteIcon> Note` While something like: `> [!NOTE] My Custom One` Would result in: `| <NoteIcon> My Custom One`
1 parent 4d8b603 commit a1bcbf4

File tree

9 files changed

+59
-18
lines changed

9 files changed

+59
-18
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Plugin to improve viewing Markdown files in Neovim
88
| -------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
99
| ![Heading Code](https://github.com/user-attachments/assets/663a34c5-0438-4688-8204-332065f65835) | ![List Table](https://github.com/user-attachments/assets/106739a4-506f-4177-93e0-fd749e5ded5c) |
1010
| ![Box Dash Quote](https://github.com/user-attachments/assets/3f76e73e-b3a0-4cd8-90c1-208c5070659c) | ![LaTeX](https://github.com/user-attachments/assets/9e8909e4-7256-45fc-b481-4aba8850ebc3) |
11-
| ![Callout](https://github.com/user-attachments/assets/089b0b45-c8ff-4b18-bf5b-d5380696fb20) | |
11+
| ![Callout](https://github.com/user-attachments/assets/4324ea72-a017-4175-9f9d-363da5e5f6ba) | |
1212

1313
<!-- panvimdoc-ignore-end -->
1414

demo/callout.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
2222
# Warning
2323
24-
> [!WARNING]
24+
> [!WARNING] Custom Title
2525
> Dastardly surprise
2626
2727
# Caution

doc/render-markdown.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*render-markdown.txt* For 0.10.0 Last change: 2024 July 31
1+
*render-markdown.txt* For 0.10.0 Last change: 2024 August 01
22

33
==============================================================================
44
Table of Contents *render-markdown-table-of-contents*

lua/render-markdown/component.lua

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1-
---@class render.md.Component
2-
---@field text string
3-
---@field highlight string
4-
51
---@class render.md.ComponentHelper
62
local M = {}
73

84
---@param config render.md.BufferConfig
95
---@param text string
106
---@param comparison 'exact'|'contains'
11-
---@return render.md.Component?
7+
---@return render.md.CustomComponent?
128
function M.callout(config, text, comparison)
139
---@param callout render.md.CustomComponent
1410
---@return boolean
@@ -23,7 +19,7 @@ function M.callout(config, text, comparison)
2319
end
2420
for _, callout in pairs(config.callout) do
2521
if matches(callout) then
26-
return { text = callout.rendered, highlight = callout.highlight }
22+
return callout
2723
end
2824
end
2925
return nil
@@ -32,7 +28,7 @@ end
3228
---@param config render.md.BufferConfig
3329
---@param text string
3430
---@param comparison 'exact'|'starts'
35-
---@return render.md.Component?
31+
---@return render.md.CustomComponent?
3632
function M.checkbox(config, text, comparison)
3733
---@param checkbox render.md.CustomComponent
3834
---@return boolean
@@ -47,7 +43,7 @@ function M.checkbox(config, text, comparison)
4743
end
4844
for _, checkbox in pairs(config.checkbox.custom) do
4945
if matches(checkbox) then
50-
return { text = checkbox.rendered, highlight = checkbox.highlight }
46+
return checkbox
5147
end
5248
end
5349
return nil

lua/render-markdown/handler/latex.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
local logger = require('render-markdown.logger')
22
local state = require('render-markdown.state')
3+
local str = require('render-markdown.str')
34
local ts = require('render-markdown.ts')
45

56
---@type table<string, string[]>
@@ -27,7 +28,7 @@ function M.parse(root, buf)
2728
local expressions = cache[info.text]
2829
if expressions == nil then
2930
local raw_expression = vim.fn.system(latex.converter, info.text)
30-
expressions = vim.split(raw_expression, '\n', { plain = true, trimempty = true })
31+
expressions = str.split(raw_expression, '\n')
3132
for _ = 1, latex.top_pad do
3233
table.insert(expressions, 1, '')
3334
end

lua/render-markdown/handler/markdown_inline.lua

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function M.parse(root, buf)
2424
if capture == 'code' then
2525
list.add_mark(marks, M.code(config, info))
2626
elseif capture == 'callout' then
27-
list.add_mark(marks, M.callout(config, info))
27+
list.add_mark(marks, M.callout(config, buf, info))
2828
elseif capture == 'link' then
2929
list.add_mark(marks, M.link(config, buf, info))
3030
else
@@ -61,14 +61,33 @@ end
6161

6262
---@private
6363
---@param config render.md.BufferConfig
64+
---@param buf integer
6465
---@param info render.md.NodeInfo
6566
---@return render.md.Mark?
66-
function M.callout(config, info)
67+
function M.callout(config, buf, info)
68+
---Support for overriding title: https://help.obsidian.md/Editing+and+formatting/Callouts#Change+the+title
69+
---@param callout render.md.CustomComponent
70+
---@return string
71+
---@return string?
72+
local function custom_title(callout)
73+
local content = ts.parent(buf, info, 'inline')
74+
if content ~= nil then
75+
local line = str.split(content.text, '\n')[1]
76+
if #line > #callout.raw and vim.startswith(line:lower(), callout.raw:lower()) then
77+
local icon = str.split(callout.rendered, ' ')[1]
78+
local title = vim.trim(line:sub(#callout.raw + 1))
79+
return icon .. ' ' .. title, ''
80+
end
81+
end
82+
return callout.rendered, nil
83+
end
84+
6785
local callout = component.callout(config, info.text, 'exact')
6886
if callout ~= nil then
6987
if not config.quote.enabled then
7088
return nil
7189
end
90+
local text, conceal = custom_title(callout)
7291
---@type render.md.Mark
7392
return {
7493
conceal = true,
@@ -77,8 +96,9 @@ function M.callout(config, info)
7796
opts = {
7897
end_row = info.end_row,
7998
end_col = info.end_col,
80-
virt_text = { { callout.text, callout.highlight } },
99+
virt_text = { { text, callout.highlight } },
81100
virt_text_pos = 'overlay',
101+
conceal = conceal,
82102
},
83103
}
84104
else
@@ -101,7 +121,7 @@ function M.callout(config, info)
101121
opts = {
102122
end_row = info.end_row,
103123
end_col = info.end_col,
104-
virt_text = { { str.pad_to(info.text, checkbox.text), checkbox.highlight } },
124+
virt_text = { { str.pad_to(info.text, checkbox.rendered), checkbox.highlight } },
105125
virt_text_pos = 'inline',
106126
conceal = '',
107127
},

lua/render-markdown/str.lua

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
---@class render.md.StringHelper
22
local M = {}
33

4+
---@param s string
5+
---@param sep string
6+
---@return string[]
7+
function M.split(s, sep)
8+
return vim.split(s, sep, { plain = true, trimempty = true })
9+
end
10+
411
---@param s? string
512
---@return integer
613
function M.width(s)

lua/render-markdown/ts.lua

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,21 @@ function M.level_in_section(info, target)
6464
return level
6565
end
6666

67+
---@param buf integer
68+
---@param info render.md.NodeInfo
69+
---@param target string
70+
---@return render.md.NodeInfo?
71+
function M.parent(buf, info, target)
72+
local parent = info.node:parent()
73+
while parent ~= nil do
74+
if parent:type() == target then
75+
return M.info(parent, buf)
76+
end
77+
parent = parent:parent()
78+
end
79+
return nil
80+
end
81+
6782
---@param buf integer
6883
---@param info render.md.NodeInfo
6984
---@param target string

tests/callout_spec.lua

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ local util = require('tests.util')
77
---@param end_col integer
88
---@param text string
99
---@param highlight string
10+
---@param conceal string?
1011
---@return render.md.MarkInfo
11-
local function callout(row, start_col, end_col, text, highlight)
12+
local function callout(row, start_col, end_col, text, highlight, conceal)
1213
---@type render.md.MarkInfo
1314
return {
1415
row = { row, row },
1516
col = { start_col, end_col },
1617
virt_text = { { text, util.hl(highlight) } },
1718
virt_text_pos = 'overlay',
19+
conceal = conceal,
1820
}
1921
end
2022

@@ -69,7 +71,7 @@ describe('callout.md', function()
6971
vim.list_extend(expected, util.heading(warning_start, 1))
7072
vim.list_extend(expected, {
7173
util.quote(warning_start + 2, '%s ', warn), -- Quote start
72-
callout(warning_start + 2, 2, 12, '󰀪 Warning', warn), -- Callout text
74+
callout(warning_start + 2, 2, 12, '󰀪 Custom Title', warn, ''), -- Callout text
7375
util.quote(warning_start + 3, '%s ', warn), -- Quote continued
7476
})
7577

0 commit comments

Comments
 (0)