Skip to content

Commit d7be79b

Browse files
feat: render list item bullet points in yaml
## Details Request: #496 Adds ability to render bullet points in yaml, primarily for people that use `obsidian` style metadata via `frontmatter`. Requires user to install `yaml` parser so that lists / list items can be queried for. New top level `yaml` configuration added similar to `html` that allows the feature (and any others potentially added later) to be disabled. Values used for rendering are currently pulled from the same configuration as `markdown` bullet point rendering, i.e. `bullet`. Currently only the `icon` and `highlight` values are used and the only rendering the happens is overlaying the icon. Any other `bullet` features like padding and scope highlighting would need to be added separately, can potentially be done if requested.
1 parent a42ee5f commit d7be79b

File tree

11 files changed

+152
-13
lines changed

11 files changed

+152
-13
lines changed

README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -878,9 +878,9 @@ require('render-markdown').setup({
878878
-- More granular configuration mechanism, allows different aspects of buffers to have their own
879879
-- behavior. Values default to the top level configuration if no override is provided. Supports
880880
-- the following fields:
881-
-- enabled, max_file_size, debounce, render_modes, anti_conceal, padding, heading, paragraph,
882-
-- code, dash, bullet, checkbox, quote, pipe_table, callout, link, sign, indent, latex, html,
883-
-- win_options
881+
-- enabled, render_modes, max_file_size, debounce, anti_conceal, bullet, callout, checkbox,
882+
-- code, dash, document, heading, html, indent, inline_highlight, latex, link, padding,
883+
-- paragraph, pipe_table, quote, sign, win_options, yaml
884884

885885
-- Override for different buflisted values, @see :h 'buflisted'.
886886
buflisted = {},
@@ -899,6 +899,12 @@ require('render-markdown').setup({
899899
-- Mapping from treesitter language to user defined handlers.
900900
-- @see [Custom Handlers](doc/custom-handlers.md)
901901
},
902+
yaml = {
903+
-- Turn on / off all yaml rendering.
904+
enabled = true,
905+
-- Additional modes to render yaml.
906+
render_modes = false,
907+
},
902908
})
903909
```
904910

doc/render-markdown.txt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -944,9 +944,9 @@ Default Configuration ~
944944
-- More granular configuration mechanism, allows different aspects of buffers to have their own
945945
-- behavior. Values default to the top level configuration if no override is provided. Supports
946946
-- the following fields:
947-
-- enabled, max_file_size, debounce, render_modes, anti_conceal, padding, heading, paragraph,
948-
-- code, dash, bullet, checkbox, quote, pipe_table, callout, link, sign, indent, latex, html,
949-
-- win_options
947+
-- enabled, render_modes, max_file_size, debounce, anti_conceal, bullet, callout, checkbox,
948+
-- code, dash, document, heading, html, indent, inline_highlight, latex, link, padding,
949+
-- paragraph, pipe_table, quote, sign, win_options, yaml
950950

951951
-- Override for different buflisted values, @see :h 'buflisted'.
952952
buflisted = {},
@@ -965,6 +965,12 @@ Default Configuration ~
965965
-- Mapping from treesitter language to user defined handlers.
966966
-- @see [Custom Handlers](doc/custom-handlers.md)
967967
},
968+
yaml = {
969+
-- Turn on / off all yaml rendering.
970+
enabled = true,
971+
-- Additional modes to render yaml.
972+
render_modes = false,
973+
},
968974
})
969975
<
970976

lua/render-markdown/config/overrides.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ M.default = {
1111
-- More granular configuration mechanism, allows different aspects of buffers to have their own
1212
-- behavior. Values default to the top level configuration if no override is provided. Supports
1313
-- the following fields:
14-
-- enabled, max_file_size, debounce, render_modes, anti_conceal, padding, heading, paragraph,
15-
-- code, dash, bullet, checkbox, quote, pipe_table, callout, link, sign, indent, latex, html,
16-
-- win_options
14+
-- enabled, render_modes, max_file_size, debounce, anti_conceal, bullet, callout, checkbox,
15+
-- code, dash, document, heading, html, indent, inline_highlight, latex, link, padding,
16+
-- paragraph, pipe_table, quote, sign, win_options, yaml
1717

1818
-- Override for different buflisted values, @see :h 'buflisted'.
1919
buflisted = {},
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---@class (exact) render.md.yaml.Config: render.md.base.Config
2+
3+
---@class render.md.yaml.Cfg
4+
local M = {}
5+
6+
---@type render.md.yaml.Config
7+
M.default = {
8+
-- Turn on / off all yaml rendering.
9+
enabled = true,
10+
-- Additional modes to render yaml.
11+
render_modes = false,
12+
}
13+
14+
---@param spec render.md.debug.ValidatorSpec
15+
function M.validate(spec)
16+
require('render-markdown.config.base').validate(spec)
17+
spec:check()
18+
end
19+
20+
return M

lua/render-markdown/core/handlers.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ M.builtin = {
1414
latex = require('render-markdown.handler.latex'),
1515
markdown = require('render-markdown.handler.markdown'),
1616
markdown_inline = require('render-markdown.handler.markdown_inline'),
17+
yaml = require('render-markdown.handler.yaml'),
1718
}
1819

1920
---called from state on setup
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
local Context = require('render-markdown.request.context')
2+
local Marks = require('render-markdown.lib.marks')
3+
local ts = require('render-markdown.core.ts')
4+
5+
---@class render.md.handler.Yaml: render.md.Handler
6+
local M = {}
7+
8+
---@param ctx render.md.handler.Context
9+
---@return render.md.Mark[]
10+
function M.parse(ctx)
11+
local query = ts.parse(
12+
'yaml',
13+
[[
14+
(block_sequence_item) @bullet
15+
]]
16+
)
17+
---@type table<string, render.md.Render>
18+
local renders = {
19+
bullet = require('render-markdown.render.yaml.bullet'),
20+
}
21+
local context = Context.get(ctx.buf)
22+
if context:skip(context.config.yaml) then
23+
return {}
24+
end
25+
local marks = Marks.new(context, true)
26+
context.view:nodes(ctx.root, query, function(capture, node)
27+
local render = renders[capture]
28+
assert(render, ('unhandled yaml capture: %s'):format(capture))
29+
render:execute(context, marks, node)
30+
end)
31+
return marks:get()
32+
end
33+
34+
return M

lua/render-markdown/health.lua

Lines changed: 8 additions & 4 deletions
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 = '8.7.1'
8+
M.version = '8.7.2'
99

1010
function M.check()
1111
M.start('versions')
@@ -23,16 +23,20 @@ function M.check()
2323
end
2424

2525
local config = state.get(0)
26-
local latex = config.latex
2726
local html = config.html
27+
local latex = config.latex
28+
local yaml = config.yaml
2829

2930
M.ts_info('markdown', true, true)
3031
M.ts_info('markdown_inline', true, false)
32+
if html.enabled then
33+
M.ts_info('html', false, false)
34+
end
3135
if latex.enabled then
3236
M.ts_info('latex', false, false)
3337
end
34-
if html.enabled then
35-
M.ts_info('html', false, false)
38+
if yaml.enabled then
39+
M.ts_info('yaml', false, false)
3640
end
3741

3842
M.start('icons')

lua/render-markdown/init.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ local M = {}
3737
---@field quote render.md.quote.Config
3838
---@field sign render.md.sign.Config
3939
---@field win_options render.md.window.Configs
40+
---@field yaml render.md.yaml.Config
4041

4142
---@private
4243
---@type boolean
@@ -101,6 +102,7 @@ M.default = {
101102
win_options = require('render-markdown.config.win_options').default,
102103
overrides = require('render-markdown.config.overrides').default,
103104
custom_handlers = require('render-markdown.config.handlers').default,
105+
yaml = require('render-markdown.config.yaml').default,
104106
}
105107

106108
---@param opts? render.md.UserConfig

lua/render-markdown/lib/config.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ function Config.new(root, enabled, buf)
3838
quote = root.quote,
3939
sign = root.sign,
4040
win_options = root.win_options,
41+
yaml = root.yaml,
4142
}
4243
config = vim.deepcopy(config)
4344
for _, name in ipairs({ 'buflisted', 'buftype', 'filetype' }) do
@@ -103,6 +104,7 @@ function Config.validate(spec)
103104
spec:nested('quote', require('render-markdown.config.quote').validate)
104105
spec:nested('sign', require('render-markdown.config.sign').validate)
105106
spec:nested('win_options', require('render-markdown.config.win_options').validate)
107+
spec:nested('yaml', require('render-markdown.config.yaml').validate)
106108
end
107109

108110
return Config
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
local Base = require('render-markdown.render.base')
2+
local list = require('render-markdown.lib.list')
3+
4+
---@class render.md.yaml.bullet.Data
5+
---@field icon? string
6+
---@field highlight? string
7+
8+
---@class render.md.render.yaml.Bullet: render.md.Render
9+
---@field private config render.md.bullet.Config
10+
local Render = setmetatable({}, Base)
11+
Render.__index = Render
12+
13+
---@protected
14+
---@return boolean
15+
function Render:setup()
16+
self.config = self.context.config.bullet
17+
if self.context:skip(self.config) then
18+
return false
19+
end
20+
return true
21+
end
22+
23+
---@protected
24+
function Render:run()
25+
---@type render.md.bullet.Context
26+
local ctx = {
27+
level = self.node:level_in('block_sequence', 'document'),
28+
index = self.node:sibling_count('block_sequence_item'),
29+
value = '-',
30+
}
31+
local icon = Render.get_string(self.config.icons, ctx)
32+
local highlight = Render.get_string(self.config.highlight, ctx)
33+
if not icon or not highlight then
34+
return
35+
end
36+
self.marks:start('bullet', self.node, {
37+
virt_text = { { icon, highlight } },
38+
virt_text_pos = 'overlay',
39+
})
40+
end
41+
42+
---@private
43+
---@param values render.md.bullet.String
44+
---@param ctx render.md.bullet.Context
45+
---@return string?
46+
function Render.get_string(values, ctx)
47+
if type(values) == 'table' then
48+
local value = list.cycle(values, ctx.level)
49+
if type(value) == 'table' then
50+
return list.clamp(value, ctx.index)
51+
else
52+
return value
53+
end
54+
elseif type(values) == 'function' then
55+
return values(ctx)
56+
else
57+
return values
58+
end
59+
end
60+
61+
return Render

0 commit comments

Comments
 (0)