Skip to content

Commit 6392a5d

Browse files
feat: add left_pad, right_pad, & min_width for headings
# Details Request: #121 This adds 3 additional heading parameters, left_pad, right_pad, and min_width. This works in an identical way to the same parameters in code blocks. left_pad can be used with any width attribute, whereas right_pad and min_width are only used for 'block' width. We do need to take additional care of various concealing behaviors which adds a bit of complexity. left_pad: moves the heading line to the left right_pad: adds a margin of background to the end of block width headings min_width: ensures that the same padding extends at least to the specified value making a uniform look easier
1 parent a48378d commit 6392a5d

File tree

9 files changed

+122
-43
lines changed

9 files changed

+122
-43
lines changed

Diff for: README.md

+20-8
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,12 @@ require('render-markdown').setup({
245245
-- block: width of the heading text
246246
-- full: full width of the window
247247
width = 'full',
248+
-- Amount of padding to add to the left of headings
249+
left_pad = 0,
250+
-- Amount of padding to add to the right of headings when width is 'block'
251+
right_pad = 0,
252+
-- Minimum width to use for headings when width is 'block'
253+
min_width = 0,
248254
-- The 'level' is used to index into the array using a clamp
249255
-- Highlight for the heading icon and extends through the entire line
250256
backgrounds = {
@@ -284,16 +290,16 @@ require('render-markdown').setup({
284290
-- An array of language names for which background highlighting will be disabled
285291
-- Likely because that language has background highlights itself
286292
disable_background = { 'diff' },
293+
-- Width of the code block background:
294+
-- block: width of the code block
295+
-- full: full width of the window
296+
width = 'full',
287297
-- Amount of padding to add to the left of code blocks
288298
left_pad = 0,
289299
-- Amount of padding to add to the right of code blocks when width is 'block'
290300
right_pad = 0,
291301
-- Minimum width to use for code blocks when width is 'block'
292302
min_width = 0,
293-
-- Width of the code block background:
294-
-- block: width of the code block
295-
-- full: full width of the window
296-
width = 'full',
297303
-- Determins how the top / bottom of code block are rendered:
298304
-- thick: use the same highlight as the code body
299305
-- thin: when lines are empty overlay the above & below icons
@@ -526,6 +532,12 @@ require('render-markdown').setup({
526532
-- block: width of the heading text
527533
-- full: full width of the window
528534
width = 'full',
535+
-- Amount of padding to add to the left of headings
536+
left_pad = 0,
537+
-- Amount of padding to add to the right of headings when width is 'block'
538+
right_pad = 0,
539+
-- Minimum width to use for headings when width is 'block'
540+
min_width = 0,
529541
-- The 'level' is used to index into the array using a clamp
530542
-- Highlight for the heading icon and extends through the entire line
531543
backgrounds = {
@@ -572,16 +584,16 @@ require('render-markdown').setup({
572584
-- An array of language names for which background highlighting will be disabled
573585
-- Likely because that language has background highlights itself
574586
disable_background = { 'diff' },
587+
-- Width of the code block background:
588+
-- block: width of the code block
589+
-- full: full width of the window
590+
width = 'full',
575591
-- Amount of padding to add to the left of code blocks
576592
left_pad = 0,
577593
-- Amount of padding to add to the right of code blocks when width is 'block'
578594
right_pad = 0,
579595
-- Minimum width to use for code blocks when width is 'block'
580596
min_width = 0,
581-
-- Width of the code block background:
582-
-- block: width of the code block
583-
-- full: full width of the window
584-
width = 'full',
585597
-- Determins how the top / bottom of code block are rendered:
586598
-- thick: use the same highlight as the code body
587599
-- thin: when lines are empty overlay the above & below icons

Diff for: doc/render-markdown.txt

+20-8
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,12 @@ Full Default Configuration ~
273273
-- block: width of the heading text
274274
-- full: full width of the window
275275
width = 'full',
276+
-- Amount of padding to add to the left of headings
277+
left_pad = 0,
278+
-- Amount of padding to add to the right of headings when width is 'block'
279+
right_pad = 0,
280+
-- Minimum width to use for headings when width is 'block'
281+
min_width = 0,
276282
-- The 'level' is used to index into the array using a clamp
277283
-- Highlight for the heading icon and extends through the entire line
278284
backgrounds = {
@@ -312,16 +318,16 @@ Full Default Configuration ~
312318
-- An array of language names for which background highlighting will be disabled
313319
-- Likely because that language has background highlights itself
314320
disable_background = { 'diff' },
321+
-- Width of the code block background:
322+
-- block: width of the code block
323+
-- full: full width of the window
324+
width = 'full',
315325
-- Amount of padding to add to the left of code blocks
316326
left_pad = 0,
317327
-- Amount of padding to add to the right of code blocks when width is 'block'
318328
right_pad = 0,
319329
-- Minimum width to use for code blocks when width is 'block'
320330
min_width = 0,
321-
-- Width of the code block background:
322-
-- block: width of the code block
323-
-- full: full width of the window
324-
width = 'full',
325331
-- Determins how the top / bottom of code block are rendered:
326332
-- thick: use the same highlight as the code body
327333
-- thin: when lines are empty overlay the above & below icons
@@ -553,6 +559,12 @@ HEADINGS *render-markdown-setup-headings*
553559
-- block: width of the heading text
554560
-- full: full width of the window
555561
width = 'full',
562+
-- Amount of padding to add to the left of headings
563+
left_pad = 0,
564+
-- Amount of padding to add to the right of headings when width is 'block'
565+
right_pad = 0,
566+
-- Minimum width to use for headings when width is 'block'
567+
min_width = 0,
556568
-- The 'level' is used to index into the array using a clamp
557569
-- Highlight for the heading icon and extends through the entire line
558570
backgrounds = {
@@ -600,16 +612,16 @@ CODE BLOCKS *render-markdown-setup-code-blocks*
600612
-- An array of language names for which background highlighting will be disabled
601613
-- Likely because that language has background highlights itself
602614
disable_background = { 'diff' },
615+
-- Width of the code block background:
616+
-- block: width of the code block
617+
-- full: full width of the window
618+
width = 'full',
603619
-- Amount of padding to add to the left of code blocks
604620
left_pad = 0,
605621
-- Amount of padding to add to the right of code blocks when width is 'block'
606622
right_pad = 0,
607623
-- Minimum width to use for code blocks when width is 'block'
608624
min_width = 0,
609-
-- Width of the code block background:
610-
-- block: width of the code block
611-
-- full: full width of the window
612-
width = 'full',
613625
-- Determins how the top / bottom of code block are rendered:
614626
-- thick: use the same highlight as the code body
615627
-- thin: when lines are empty overlay the above & below icons

Diff for: lua/render-markdown/handler/markdown.lua

+44-8
Original file line numberDiff line numberDiff line change
@@ -83,28 +83,63 @@ function Handler:heading(info)
8383
end
8484

8585
local level = str.width(info.text)
86-
local icon = list.cycle(heading.icons, level)
8786
local foreground = list.clamp(heading.foregrounds, level)
8887
local background = list.clamp(heading.backgrounds, level)
8988

89+
local icon_width = self:heading_icon(info, level, foreground, background)
90+
if heading.sign then
91+
self:sign(info, list.cycle(heading.signs, level), foreground)
92+
end
93+
9094
self:add(true, info.start_row, 0, {
9195
end_row = info.end_row + 1,
9296
end_col = 0,
9397
hl_group = background,
94-
hl_eol = heading.width == 'full',
98+
hl_eol = true,
9599
})
96100

97-
if heading.sign then
98-
self:sign(info, list.cycle(heading.signs, level), foreground)
101+
if heading.width == 'block' then
102+
-- Overwrite anything beyond left_pad + heading width + right_pad with Normal
103+
local width = heading.left_pad + icon_width + heading.right_pad
104+
local content = ts.sibling(self.buf, info, 'inline')
105+
if content ~= nil then
106+
width = width + str.width(content.text) - ts.concealed(self.buf, content)
107+
end
108+
self:add(true, info.start_row, 0, {
109+
priority = 0,
110+
virt_text = { { str.pad(vim.o.columns * 2), 'Normal' } },
111+
virt_text_win_col = math.max(width, heading.min_width),
112+
})
99113
end
100114

101-
if icon == nil then
102-
return
115+
if heading.left_pad > 0 then
116+
self:add(false, info.start_row, 0, {
117+
priority = 0,
118+
virt_text = { { str.pad(heading.left_pad), background } },
119+
virt_text_pos = 'inline',
120+
})
103121
end
122+
end
123+
124+
---@private
125+
---@param info render.md.NodeInfo
126+
---@param level integer
127+
---@param foreground string
128+
---@param background string
129+
---@return integer
130+
function Handler:heading_icon(info, level, foreground, background)
131+
local heading = self.config.heading
132+
local icon = list.cycle(heading.icons, level)
133+
104134
-- Available width is level + 1 - concealed, where level = number of `#` characters, one
105135
-- is added to account for the space after the last `#` but before the heading title,
106136
-- and concealed text is subtracted since that space is not usable
107-
local padding = level + 1 - ts.concealed(self.buf, info) - str.width(icon)
137+
local width = level + 1 - ts.concealed(self.buf, info)
138+
if icon == nil then
139+
return width
140+
end
141+
142+
local padding = width - str.width(icon)
108143
if heading.position == 'inline' or padding < 0 then
109144
self:add(true, info.start_row, info.start_col, {
110145
end_row = info.end_row,
@@ -113,13 +148,15 @@ function Handler:heading(info)
113148
virt_text_pos = 'inline',
114149
conceal = '',
115150
})
151+
return str.width(icon)
116152
else
117153
self:add(true, info.start_row, info.start_col, {
118154
end_row = info.end_row,
119155
end_col = info.end_col,
120156
virt_text = { { str.pad(padding, icon), { foreground, background } } },
121157
virt_text_pos = 'overlay',
122158
})
159+
return width
123160
end
124161
end
125162

@@ -284,7 +321,6 @@ function Handler:code_left_pad(code_block, add_background)
284321
for row = code_block.start_row, code_block.end_row - 1 do
285322
-- Uses a low priority so other marks are loaded first and included in padding
286323
self:add(false, row, code_block.col, {
287-
end_row = row + 1,
288324
priority = 0,
289325
virt_text = { { padding, highlight } },
290326
virt_text_pos = 'inline',

Diff for: lua/render-markdown/handler/markdown_inline.lua

+7-3
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,28 @@ function Handler:shortcut(info)
7373
self:callout(info, callout)
7474
return
7575
end
76+
7677
local checkbox = component.checkbox(self.config, info.text, 'exact')
7778
if checkbox ~= nil then
7879
self:checkbox(info, checkbox)
7980
return
8081
end
82+
8183
local line = vim.api.nvim_buf_get_lines(self.buf, info.start_row, info.start_row + 1, false)[1]
8284
if line:find('[' .. info.text .. ']', 1, true) ~= nil then
8385
self:wiki_link(info)
86+
return
8487
end
8588
end
8689

8790
---@private
8891
---@param info render.md.NodeInfo
8992
---@param callout render.md.CustomComponent
9093
function Handler:callout(info, callout)
94+
if not self.config.quote.enabled then
95+
return
96+
end
97+
9198
---Support for overriding title: https://help.obsidian.md/Editing+and+formatting/Callouts#Change+the+title
9299
---@return string, string?
93100
local function custom_title()
@@ -103,9 +110,6 @@ function Handler:callout(info, callout)
103110
return callout.rendered, nil
104111
end
105112

106-
if not self.config.quote.enabled then
107-
return
108-
end
109113
local text, conceal = custom_title()
110114
self:add(info.start_row, info.start_col, {
111115
end_row = info.end_row,

Diff for: lua/render-markdown/health.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ local M = {}
55

66
---@private
77
---@type string
8-
M.version = '6.0.3'
8+
M.version = '6.0.4'
99

1010
function M.check()
1111
vim.health.start('render-markdown.nvim [version]')

Diff for: lua/render-markdown/init.lua

+14-5
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,10 @@ local M = {}
8888
---@field public style? 'full'|'normal'|'language'|'none'
8989
---@field public position? 'left'|'right'
9090
---@field public disable_background? string[]
91+
---@field public width? 'full'|'block'
9192
---@field public left_pad? integer
9293
---@field public right_pad? integer
9394
---@field public min_width? integer
94-
---@field public width? 'full'|'block'
9595
---@field public border? 'thin'|'thick'
9696
---@field public above? string
9797
---@field public below? string
@@ -105,6 +105,9 @@ local M = {}
105105
---@field public icons? string[]
106106
---@field public signs? string[]
107107
---@field public width? 'full'|'block'
108+
---@field public left_pad? integer
109+
---@field public right_pad? integer
110+
---@field public min_width? integer
108111
---@field public backgrounds? string[]
109112
---@field public foregrounds? string[]
110113

@@ -251,6 +254,12 @@ M.default_config = {
251254
-- block: width of the heading text
252255
-- full: full width of the window
253256
width = 'full',
257+
-- Amount of padding to add to the left of headings
258+
left_pad = 0,
259+
-- Amount of padding to add to the right of headings when width is 'block'
260+
right_pad = 0,
261+
-- Minimum width to use for headings when width is 'block'
262+
min_width = 0,
254263
-- The 'level' is used to index into the array using a clamp
255264
-- Highlight for the heading icon and extends through the entire line
256265
backgrounds = {
@@ -290,16 +299,16 @@ M.default_config = {
290299
-- An array of language names for which background highlighting will be disabled
291300
-- Likely because that language has background highlights itself
292301
disable_background = { 'diff' },
302+
-- Width of the code block background:
303+
-- block: width of the code block
304+
-- full: full width of the window
305+
width = 'full',
293306
-- Amount of padding to add to the left of code blocks
294307
left_pad = 0,
295308
-- Amount of padding to add to the right of code blocks when width is 'block'
296309
right_pad = 0,
297310
-- Minimum width to use for code blocks when width is 'block'
298311
min_width = 0,
299-
-- Width of the code block background:
300-
-- block: width of the code block
301-
-- full: full width of the window
302-
width = 'full',
303312
-- Determins how the top / bottom of code block are rendered:
304313
-- thick: use the same highlight as the code body
305314
-- thin: when lines are empty overlay the above & below icons

Diff for: lua/render-markdown/state.lua

+4-1
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@ function M.validate()
169169
icons = string_array(heading.icons, nilable),
170170
signs = string_array(heading.signs, nilable),
171171
width = one_of(heading.width, { 'full', 'block' }, {}, nilable),
172+
left_pad = { heading.left_pad, 'number', nilable },
173+
right_pad = { heading.right_pad, 'number', nilable },
174+
min_width = { heading.min_width, 'number', nilable },
172175
backgrounds = string_array(heading.backgrounds, nilable),
173176
foregrounds = string_array(heading.foregrounds, nilable),
174177
})
@@ -182,10 +185,10 @@ function M.validate()
182185
style = one_of(code.style, { 'full', 'normal', 'language', 'none' }, {}, nilable),
183186
position = one_of(code.position, { 'left', 'right' }, {}, nilable),
184187
disable_background = string_array(code.disable_background, nilable),
188+
width = one_of(code.width, { 'full', 'block' }, {}, nilable),
185189
left_pad = { code.left_pad, 'number', nilable },
186190
right_pad = { code.right_pad, 'number', nilable },
187191
min_width = { code.min_width, 'number', nilable },
188-
width = one_of(code.width, { 'full', 'block' }, {}, nilable),
189192
border = one_of(code.border, { 'thin', 'thick' }, {}, nilable),
190193
above = { code.above, 'string', nilable },
191194
below = { code.below, 'string', nilable },

Diff for: lua/render-markdown/types.lua

+4-1
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,10 @@
7777
---@field public style 'full'|'normal'|'language'|'none'
7878
---@field public position 'left'|'right'
7979
---@field public disable_background string[]
80+
---@field public width 'full'|'block'
8081
---@field public left_pad integer
8182
---@field public right_pad integer
8283
---@field public min_width integer
83-
---@field public width 'full'|'block'
8484
---@field public border 'thin'|'thick'
8585
---@field public above string
8686
---@field public below string
@@ -94,6 +94,9 @@
9494
---@field public icons string[]
9595
---@field public signs string[]
9696
---@field public width 'full'|'block'
97+
---@field public left_pad integer
98+
---@field public right_pad integer
99+
---@field public min_width integer
97100
---@field public backgrounds string[]
98101
---@field public foregrounds string[]
99102

0 commit comments

Comments
 (0)