Skip to content

Commit bab0663

Browse files
feat: allow heading icons to be a function, provide section nesting as input
## Details Request: #286 This change allows `heading.icons` to be a function which returns a `string` that will be used as the icon. The input to the function is an `integer[]` which describes the nesting level of the current heading at all parent levels. An example configuration would look like: ```lua require('render-markdown').setup({ heading = { icons = function(sections) return table.concat(sections, '.') .. '. ' end, }, }) ``` Which when rendering: ``` # Foo # Bar ## Baz ``` Results in: ``` 1. Foo 2. Bar 2.1. Baz ```
1 parent 7b1b15f commit bab0663

File tree

8 files changed

+52
-25
lines changed

8 files changed

+52
-25
lines changed

README.md

+10-8
Original file line numberDiff line numberDiff line change
@@ -259,15 +259,16 @@ require('render-markdown').setup({
259259
render_modes = false,
260260
-- Turn on / off any sign column related rendering
261261
sign = true,
262+
-- Replaces '#+' of 'atx_h._marker'
263+
-- The number of '#' in the heading determines the 'level'
264+
-- The 'level' is used to index into the list using a cycle
265+
-- If the value is a function the input is the nesting level of the heading within sections
266+
icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' },
262267
-- Determines how icons fill the available space:
263268
-- right: '#'s are concealed and icon is appended to right side
264269
-- inline: '#'s are concealed and icon is inlined on left side
265270
-- overlay: icon is left padded with spaces and inserted on left hiding any additional '#'
266271
position = 'overlay',
267-
-- Replaces '#+' of 'atx_h._marker'
268-
-- The number of '#' in the heading determines the 'level'
269-
-- The 'level' is used to index into the list using a cycle
270-
icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' },
271272
-- Added to the sign column if enabled
272273
-- The 'level' is used to index into the list using a cycle
273274
signs = { '󰫎 ' },
@@ -734,15 +735,16 @@ require('render-markdown').setup({
734735
render_modes = false,
735736
-- Turn on / off any sign column related rendering
736737
sign = true,
738+
-- Replaces '#+' of 'atx_h._marker'
739+
-- The number of '#' in the heading determines the 'level'
740+
-- The 'level' is used to index into the list using a cycle
741+
-- If the value is a function the input is the nesting level of the heading within sections
742+
icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' },
737743
-- Determines how icons fill the available space:
738744
-- right: '#'s are concealed and icon is appended to right side
739745
-- inline: '#'s are concealed and icon is inlined on left side
740746
-- overlay: icon is left padded with spaces and inserted on left hiding any additional '#'
741747
position = 'overlay',
742-
-- Replaces '#+' of 'atx_h._marker'
743-
-- The number of '#' in the heading determines the 'level'
744-
-- The 'level' is used to index into the list using a cycle
745-
icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' },
746748
-- Added to the sign column if enabled
747749
-- The 'level' is used to index into the list using a cycle
748750
signs = { '󰫎 ' },

doc/render-markdown.txt

+10-8
Original file line numberDiff line numberDiff line change
@@ -315,15 +315,16 @@ Default Configuration ~
315315
render_modes = false,
316316
-- Turn on / off any sign column related rendering
317317
sign = true,
318+
-- Replaces '#+' of 'atx_h._marker'
319+
-- The number of '#' in the heading determines the 'level'
320+
-- The 'level' is used to index into the list using a cycle
321+
-- If the value is a function the input is the nesting level of the heading within sections
322+
icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' },
318323
-- Determines how icons fill the available space:
319324
-- right: '#'s are concealed and icon is appended to right side
320325
-- inline: '#'s are concealed and icon is inlined on left side
321326
-- overlay: icon is left padded with spaces and inserted on left hiding any additional '#'
322327
position = 'overlay',
323-
-- Replaces '#+' of 'atx_h._marker'
324-
-- The number of '#' in the heading determines the 'level'
325-
-- The 'level' is used to index into the list using a cycle
326-
icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' },
327328
-- Added to the sign column if enabled
328329
-- The 'level' is used to index into the list using a cycle
329330
signs = { '󰫎 ' },
@@ -788,15 +789,16 @@ Heading Configuration ~
788789
render_modes = false,
789790
-- Turn on / off any sign column related rendering
790791
sign = true,
792+
-- Replaces '#+' of 'atx_h._marker'
793+
-- The number of '#' in the heading determines the 'level'
794+
-- The 'level' is used to index into the list using a cycle
795+
-- If the value is a function the input is the nesting level of the heading within sections
796+
icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' },
791797
-- Determines how icons fill the available space:
792798
-- right: '#'s are concealed and icon is appended to right side
793799
-- inline: '#'s are concealed and icon is inlined on left side
794800
-- overlay: icon is left padded with spaces and inserted on left hiding any additional '#'
795801
position = 'overlay',
796-
-- Replaces '#+' of 'atx_h._marker'
797-
-- The number of '#' in the heading determines the 'level'
798-
-- The 'level' is used to index into the list using a cycle
799-
icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' },
800802
-- Added to the sign column if enabled
801803
-- The 'level' is used to index into the list using a cycle
802804
signs = { '󰫎 ' },

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 = '7.8.1'
8+
M.version = '7.8.2'
99

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

lua/render-markdown/init.lua

+9-5
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,16 @@ local M = {}
171171
---@field public left_margin? number
172172
---@field public min_width? integer
173173

174+
---@alias render.md.heading.Icons
175+
---| string[]
176+
---| fun(sections: integer[]): string?
174177
---@alias render.md.heading.Position 'overlay'|'inline'|'right'
175178
---@alias render.md.heading.Width 'full'|'block'
176179

177180
---@class (exact) render.md.UserHeading: render.md.UserBaseComponent
178181
---@field public sign? boolean
182+
---@field public icons? render.md.heading.Icons
179183
---@field public position? render.md.heading.Position
180-
---@field public icons? string[]
181184
---@field public signs? string[]
182185
---@field public width? render.md.heading.Width|(render.md.heading.Width)[]
183186
---@field public left_margin? number|number[]
@@ -353,15 +356,16 @@ M.default_config = {
353356
render_modes = false,
354357
-- Turn on / off any sign column related rendering
355358
sign = true,
359+
-- Replaces '#+' of 'atx_h._marker'
360+
-- The number of '#' in the heading determines the 'level'
361+
-- The 'level' is used to index into the list using a cycle
362+
-- If the value is a function the input is the nesting level of the heading within sections
363+
icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' },
356364
-- Determines how icons fill the available space:
357365
-- right: '#'s are concealed and icon is appended to right side
358366
-- inline: '#'s are concealed and icon is inlined on left side
359367
-- overlay: icon is left padded with spaces and inserted on left hiding any additional '#'
360368
position = 'overlay',
361-
-- Replaces '#+' of 'atx_h._marker'
362-
-- The number of '#' in the heading determines the 'level'
363-
-- The 'level' is used to index into the list using a cycle
364-
icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' },
365369
-- Added to the sign column if enabled
366370
-- The 'level' is used to index into the list using a cycle
367371
signs = { '󰫎 ' },

lua/render-markdown/lib/node.lua

+11
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,17 @@ function Node:has_error()
4848
return self.node:has_error()
4949
end
5050

51+
---@return integer[]
52+
function Node:sections()
53+
local result, section = {}, self:parent('section')
54+
while section ~= nil do
55+
local count = section:sibling_count('section')
56+
table.insert(result, 1, count)
57+
section = section:parent('section')
58+
end
59+
return result
60+
end
61+
5162
---@param parent boolean
5263
---@return integer
5364
function Node:heading_level(parent)

lua/render-markdown/render/heading.lua

+8-1
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,18 @@ function Render:setup()
5252
return false
5353
end
5454

55+
local icon, icons = nil, self.heading.icons
56+
if type(icons) == 'function' then
57+
icon = icons(self.node:sections())
58+
else
59+
icon = List.cycle(icons, level)
60+
end
61+
5562
self.data = {
5663
atx = atx,
5764
marker = marker,
5865
level = level,
59-
icon = List.cycle(self.heading.icons, level),
66+
icon = icon,
6067
sign = List.cycle(self.heading.signs, level),
6168
foreground = List.clamp(self.heading.foregrounds, level),
6269
background = List.clamp(self.heading.backgrounds, level),

lua/render-markdown/state.lua

+2-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ function M.validate()
163163
:type({ 'above', 'below' }, 'string')
164164
:list('border', 'boolean', 'boolean')
165165
:list({ 'left_margin', 'left_pad', 'right_pad', 'min_width' }, 'number', 'number')
166-
:list({ 'icons', 'signs', 'backgrounds', 'foregrounds' }, 'string')
166+
:list({ 'signs', 'backgrounds', 'foregrounds' }, 'string')
167+
:list('icons', 'string', 'function')
167168
:one_of('position', { 'overlay', 'inline', 'right' })
168169
:one_or_list_of('width', { 'full', 'block' })
169170
:check()

lua/render-markdown/types.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@
144144

145145
---@class (exact) render.md.Heading: render.md.BaseComponent
146146
---@field public sign boolean
147+
---@field public icons render.md.heading.Icons
147148
---@field public position render.md.heading.Position
148-
---@field public icons string[]
149149
---@field public signs string[]
150150
---@field public width render.md.heading.Width|(render.md.heading.Width)[]
151151
---@field public left_margin number|number[]

0 commit comments

Comments
 (0)