Skip to content

Commit f06d19a

Browse files
feat: heading width based on level
## Details Request: #126 The `heading -> width` option is now allowed to be `block`, `width`, or an array of these 2 values. If it is an array we index into it using a clamp based on the heading level. Requires a new kind of validation logic but not too bad, seems to cover all cases. Also required moving list class to generics, which was easy. Move all union strings to type alias annotations so exact values can be defined once and reused as needed.
1 parent 881b519 commit f06d19a

File tree

10 files changed

+101
-37
lines changed

10 files changed

+101
-37
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ require('render-markdown').setup({
247247
-- Width of the heading background:
248248
-- block: width of the heading text
249249
-- full: full width of the window
250+
-- Can also be an array of the above values in which case the 'level' is used
251+
-- to index into the array using a clamp
250252
width = 'full',
251253
-- Amount of padding to add to the left of headings
252254
left_pad = 0,
@@ -544,6 +546,8 @@ require('render-markdown').setup({
544546
-- Width of the heading background:
545547
-- block: width of the heading text
546548
-- full: full width of the window
549+
-- Can also be an array of the above values in which case the 'level' is used
550+
-- to index into the array using a clamp
547551
width = 'full',
548552
-- Amount of padding to add to the left of headings
549553
left_pad = 0,

doc/render-markdown.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ Full Default Configuration ~
276276
-- Width of the heading background:
277277
-- block: width of the heading text
278278
-- full: full width of the window
279+
-- Can also be an array of the above values in which case the 'level' is used
280+
-- to index into the array using a clamp
279281
width = 'full',
280282
-- Amount of padding to add to the left of headings
281283
left_pad = 0,
@@ -573,6 +575,8 @@ Wiki Page
573575
-- Width of the heading background:
574576
-- block: width of the heading text
575577
-- full: full width of the window
578+
-- Can also be an array of the above values in which case the 'level' is used
579+
-- to index into the array using a clamp
576580
width = 'full',
577581
-- Amount of padding to add to the left of headings
578582
left_pad = 0,

lua/render-markdown/handler/markdown.lua

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ function Handler:heading(info)
8989
local level = str.width(info.text)
9090
local foreground = list.clamp(heading.foregrounds, level)
9191
local background = list.clamp(heading.backgrounds, level)
92+
local heading_width = heading.width
93+
if type(heading_width) == 'table' then
94+
heading_width = list.clamp(heading_width, level)
95+
end
9296

9397
local icon_width = self:heading_icon(info, level, foreground, background)
9498
if heading.sign then
@@ -102,8 +106,8 @@ function Handler:heading(info)
102106
hl_eol = true,
103107
})
104108

105-
local width = self:heading_width(info, icon_width)
106-
if heading.width == 'block' then
109+
local width = self:heading_width(info, heading_width, icon_width)
110+
if heading_width == 'block' then
107111
-- Overwrite anything beyond width with Normal
108112
self:add(true, info.start_row, 0, {
109113
priority = 0,
@@ -165,11 +169,12 @@ end
165169

166170
---@private
167171
---@param info render.md.NodeInfo
172+
---@param heading_width render.md.heading.Width
168173
---@param icon_width integer
169174
---@return integer
170-
function Handler:heading_width(info, icon_width)
175+
function Handler:heading_width(info, heading_width, icon_width)
171176
local heading = self.config.heading
172-
if heading.width == 'block' then
177+
if heading_width == 'block' then
173178
local width = heading.left_pad + icon_width + heading.right_pad
174179
local content = info:sibling('inline')
175180
if content ~= nil then

lua/render-markdown/health.lua

Lines changed: 1 addition & 1 deletion
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.10'
8+
M.version = '6.0.11'
99

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

lua/render-markdown/init.lua

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,13 @@ local M = {}
3838
---@field public highlight? string
3939
---@field public custom? table<string, render.md.UserLinkComponent>
4040

41+
---@alias render.md.table.Style 'full'|'normal'|'none'
42+
---@alias render.md.table.Cell 'padded'|'raw'|'overlay'
43+
4144
---@class (exact) render.md.UserPipeTable
4245
---@field public enabled? boolean
43-
---@field public style? 'full'|'normal'|'none'
44-
---@field public cell? 'padded'|'raw'|'overlay'
46+
---@field public style? render.md.table.Style
47+
---@field public cell? render.md.table.Cell
4548
---@field public border? string[]
4649
---@field public alignment_indicator? string
4750
---@field public head? string
@@ -82,29 +85,37 @@ local M = {}
8285
---@field public width? 'full'|integer
8386
---@field public highlight? string
8487

88+
---@alias render.md.code.Style 'full'|'normal'|'language'|'none'
89+
---@alias render.md.code.Position 'left'|'right'
90+
---@alias render.md.code.Width 'full'|'block'
91+
---@alias render.md.code.Border 'thin'|'thick'
92+
8593
---@class (exact) render.md.UserCode
8694
---@field public enabled? boolean
8795
---@field public sign? boolean
88-
---@field public style? 'full'|'normal'|'language'|'none'
89-
---@field public position? 'left'|'right'
96+
---@field public style? render.md.code.Style
97+
---@field public position? render.md.code.Position
9098
---@field public disable_background? string[]
91-
---@field public width? 'full'|'block'
99+
---@field public width? render.md.code.Width
92100
---@field public left_pad? integer
93101
---@field public right_pad? integer
94102
---@field public min_width? integer
95-
---@field public border? 'thin'|'thick'
103+
---@field public border? render.md.code.Border
96104
---@field public above? string
97105
---@field public below? string
98106
---@field public highlight? string
99107
---@field public highlight_inline? string
100108

109+
---@alias render.md.heading.Position 'overlay'|'inline'
110+
---@alias render.md.heading.Width 'full'|'block'
111+
101112
---@class (exact) render.md.UserHeading
102113
---@field public enabled? boolean
103114
---@field public sign? boolean
104-
---@field public position? 'overlay'|'inline'
115+
---@field public position? render.md.heading.Position
105116
---@field public icons? string[]
106117
---@field public signs? string[]
107-
---@field public width? 'full'|'block'
118+
---@field public width? render.md.heading.Width|(render.md.heading.Width)[]
108119
---@field public left_pad? integer
109120
---@field public right_pad? integer
110121
---@field public min_width? integer
@@ -139,12 +150,15 @@ local M = {}
139150
---@field public sign? render.md.UserSign
140151
---@field public win_options? table<string, render.md.UserWindowOption>
141152

153+
---@alias render.md.config.Preset 'none'|'lazy'|'obsidian'
154+
---@alias render.md.config.LogLevel 'debug'|'error'
155+
142156
---@class (exact) render.md.UserConfig: render.md.UserBufferConfig
143-
---@field public preset? 'none'|'lazy'|'obsidian'
157+
---@field public preset? render.md.config.Preset
144158
---@field public markdown_query? string
145159
---@field public markdown_quote_query? string
146160
---@field public inline_query? string
147-
---@field public log_level? 'debug'|'error'
161+
---@field public log_level? render.md.config.LogLevel
148162
---@field public file_types? string[]
149163
---@field public acknowledge_conflicts? boolean
150164
---@field public latex? render.md.UserLatex
@@ -257,6 +271,8 @@ M.default_config = {
257271
-- Width of the heading background:
258272
-- block: width of the heading text
259273
-- full: full width of the window
274+
-- Can also be an array of the above values in which case the 'level' is used
275+
-- to index into the array using a clamp
260276
width = 'full',
261277
-- Amount of padding to add to the left of headings
262278
left_pad = 0,

lua/render-markdown/list.lua

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,21 @@ function M.add_mark(marks, conceal, start_row, start_col, opts)
2727
return true
2828
end
2929

30-
---@param values string[]
30+
---@generic T
31+
---@param values T[]
3132
---@param index integer
32-
---@return string?
33+
---@return T?
3334
function M.cycle(values, index)
3435
if #values == 0 then
3536
return nil
3637
end
3738
return values[((index - 1) % #values) + 1]
3839
end
3940

40-
---@param values string[]
41+
---@generic T
42+
---@param values T[]
4143
---@param index integer
42-
---@return string
44+
---@return T
4345
function M.clamp(values, index)
4446
assert(#values >= 1, 'Must have at least one value')
4547
return values[math.min(index, #values)]

lua/render-markdown/logger.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function log.reset()
2929
log.entries = {}
3030
end
3131

32-
---@param level string
32+
---@param level render.md.config.LogLevel
3333
---@param name string
3434
---@param message any
3535
function log.add(level, name, message)

lua/render-markdown/parser/pipe_table.lua

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ local logger = require('render-markdown.logger')
44
---@class render.md.parser.PipeTable
55
local M = {}
66

7+
---@alias render.md.table.Alignment 'left'|'right'|'center'|'default'
8+
79
---@class render.md.parsed.TableColumn
810
---@field width integer
9-
---@field alignment 'left'|'right'|'center'|'default'
11+
---@field alignment render.md.table.Alignment
1012

1113
---@class render.md.parsed.PipeTable
1214
---@field head render.md.NodeInfo
@@ -86,7 +88,7 @@ end
8688

8789
---@private
8890
---@param cell render.md.NodeInfo
89-
---@return 'left'|'right'|'center'|'default'
91+
---@return render.md.table.Alignment
9092
function M.parse_alignment(cell)
9193
local align_left = cell:child('pipe_table_align_left') ~= nil
9294
local align_right = cell:child('pipe_table_align_right') ~= nil

lua/render-markdown/state.lua

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ local configs = {}
77
---@class render.md.State
88
---@field private config render.md.Config
99
---@field enabled boolean
10-
---@field log_level 'debug'|'error'
10+
---@field log_level render.md.config.LogLevel
1111
---@field file_types string[]
1212
---@field acknowledge_conflicts boolean
1313
---@field latex render.md.Latex
@@ -106,6 +106,37 @@ function M.validate()
106106
}
107107
end
108108

109+
---@param value any
110+
---@param valid_values string[]
111+
---@param nilable boolean
112+
---@return vim.validate.Spec
113+
local function one_or_array_of(value, valid_values, nilable)
114+
local description = 'one or array of ' .. vim.inspect(valid_values)
115+
if nilable then
116+
description = description .. ' or nil'
117+
end
118+
return {
119+
value,
120+
function(v)
121+
if v == nil then
122+
return nilable
123+
elseif type(v) == 'string' then
124+
return vim.tbl_contains(valid_values, v)
125+
elseif type(v) == 'table' then
126+
for i, item in ipairs(v) do
127+
if not vim.tbl_contains(valid_values, item) then
128+
return false, string.format('Index %d is %s', i, item)
129+
end
130+
end
131+
return true
132+
else
133+
return false
134+
end
135+
end,
136+
description,
137+
}
138+
end
139+
109140
---@param value string[]
110141
---@param nilable boolean
111142
---@return vim.validate.Spec
@@ -119,15 +150,15 @@ function M.validate()
119150
function(v)
120151
if v == nil then
121152
return nilable
122-
elseif type(v) ~= 'table' then
123-
return false
124-
else
153+
elseif type(v) == 'table' then
125154
for i, item in ipairs(v) do
126155
if type(item) ~= 'string' then
127156
return false, string.format('Index %d is %s', i, type(item))
128157
end
129158
end
130159
return true
160+
else
161+
return false
131162
end
132163
end,
133164
description,
@@ -168,7 +199,7 @@ function M.validate()
168199
position = one_of(heading.position, { 'overlay', 'inline' }, {}, nilable),
169200
icons = string_array(heading.icons, nilable),
170201
signs = string_array(heading.signs, nilable),
171-
width = one_of(heading.width, { 'full', 'block' }, {}, nilable),
202+
width = one_or_array_of(heading.width, { 'full', 'block' }, nilable),
172203
left_pad = { heading.left_pad, 'number', nilable },
173204
right_pad = { heading.right_pad, 'number', nilable },
174205
min_width = { heading.min_width, 'number', nilable },

lua/render-markdown/types.lua

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929

3030
---@class (exact) render.md.PipeTable
3131
---@field public enabled boolean
32-
---@field public style 'full'|'normal'|'none'
33-
---@field public cell 'padded'|'raw'|'overlay'
32+
---@field public style render.md.table.Style
33+
---@field public cell render.md.table.Cell
3434
---@field public border string[]
3535
---@field public alignment_indicator string
3636
---@field public head string
@@ -74,14 +74,14 @@
7474
---@class (exact) render.md.Code
7575
---@field public enabled boolean
7676
---@field public sign boolean
77-
---@field public style 'full'|'normal'|'language'|'none'
78-
---@field public position 'left'|'right'
77+
---@field public style render.md.code.Style
78+
---@field public position render.md.code.Position
7979
---@field public disable_background string[]
80-
---@field public width 'full'|'block'
80+
---@field public width render.md.code.Width
8181
---@field public left_pad integer
8282
---@field public right_pad integer
8383
---@field public min_width integer
84-
---@field public border 'thin'|'thick'
84+
---@field public border render.md.code.Border
8585
---@field public above string
8686
---@field public below string
8787
---@field public highlight string
@@ -90,10 +90,10 @@
9090
---@class (exact) render.md.Heading
9191
---@field public enabled boolean
9292
---@field public sign boolean
93-
---@field public position 'overlay'|'inline'
93+
---@field public position render.md.heading.Position
9494
---@field public icons string[]
9595
---@field public signs string[]
96-
---@field public width 'full'|'block'
96+
---@field public width render.md.heading.Width|(render.md.heading.Width)[]
9797
---@field public left_pad integer
9898
---@field public right_pad integer
9999
---@field public min_width integer
@@ -129,11 +129,11 @@
129129
---@field public win_options table<string, render.md.WindowOption>
130130

131131
---@class (exact) render.md.Config: render.md.BufferConfig
132-
---@field public preset 'none'|'lazy'|'obsidian'
132+
---@field public preset render.md.config.Preset
133133
---@field public markdown_query string
134134
---@field public markdown_quote_query string
135135
---@field public inline_query string
136-
---@field public log_level 'debug'|'error'
136+
---@field public log_level render.md.config.LogLevel
137137
---@field public file_types string[]
138138
---@field public acknowledge_conflicts boolean
139139
---@field public latex render.md.Latex

0 commit comments

Comments
 (0)