Skip to content

Commit b456d53

Browse files
chore(refactor): improve encapsulation, create validator class for config validation
1 parent 0986638 commit b456d53

File tree

11 files changed

+388
-396
lines changed

11 files changed

+388
-396
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
[c686970](https://github.com/MeanderingProgrammer/render-markdown.nvim/commit/c68697085441d03a20eee15d4d78e2e5a771569a)
99
- configurable padding highlight [#176](https://github.com/MeanderingProgrammer/render-markdown.nvim/issues/176)
1010
[095078d](https://github.com/MeanderingProgrammer/render-markdown.nvim/commit/095078d931ce23b544face8ca7b845adf7fad7e9)
11+
- pad setext header lines [75a0a95](https://github.com/MeanderingProgrammer/render-markdown.nvim/commit/75a0a9596a91130fae43d3b7c0d6c651645ef1df)
12+
- center headings and code blocks [#179](https://github.com/MeanderingProgrammer/render-markdown.nvim/issues/179)
13+
[0986638](https://github.com/MeanderingProgrammer/render-markdown.nvim/commit/0986638b381a4b01eb108bb946f3a67a9eb3d0ec)
1114

1215
### Bug Fixes
1316

lua/render-markdown/api.lua

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ function M.toggle()
1717
end
1818

1919
function M.log()
20-
local log = require('render-markdown.core.log')
21-
log.flush()
22-
vim.cmd.tabnew(log.file)
20+
require('render-markdown.core.log').open()
2321
end
2422

2523
function M.expand()

lua/render-markdown/core/buffer_state.lua

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
---@field private buf integer
33
---@field private timer uv_timer_t
44
---@field private running boolean
5-
---@field marks? render.md.Extmark[]
5+
---@field private marks? render.md.Extmark[]
66
local BufferState = {}
77
BufferState.__index = BufferState
88

@@ -29,4 +29,19 @@ function BufferState:debounce(ms, callback)
2929
end
3030
end
3131

32+
---@return boolean
33+
function BufferState:has_marks()
34+
return self.marks ~= nil
35+
end
36+
37+
---@return render.md.Extmark[]
38+
function BufferState:get_marks()
39+
return self.marks or {}
40+
end
41+
42+
---@param marks? render.md.Extmark[]
43+
function BufferState:set_marks(marks)
44+
self.marks = marks
45+
end
46+
3247
return BufferState

lua/render-markdown/core/extmark.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---@class render.md.Extmark
22
---@field private id? integer
3-
---@field mark render.md.Mark
3+
---@field private mark render.md.Mark
44
local Extmark = {}
55
Extmark.__index = Extmark
66

@@ -13,6 +13,11 @@ function Extmark.new(mark)
1313
return self
1414
end
1515

16+
---@return render.md.Mark
17+
function Extmark:get_mark()
18+
return self.mark
19+
end
20+
1621
---@param hidden Range2?
1722
---@return boolean
1823
function Extmark:overlaps(hidden)

lua/render-markdown/core/log.lua

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ local util = require('render-markdown.core.util')
99
---@class render.md.Log
1010
---@field private level render.md.config.LogLevel
1111
---@field private entries render.md.log.Entry[]
12-
---@field file string
12+
---@field private file string
1313
local M = {}
1414

1515
---@param level render.md.config.LogLevel
@@ -29,6 +29,11 @@ function M.setup(level)
2929
end
3030
end
3131

32+
function M.open()
33+
M.flush()
34+
vim.cmd.tabnew(M.file)
35+
end
36+
3237
---@param capture string
3338
---@param info render.md.NodeInfo
3439
function M.node_info(capture, info)
@@ -105,6 +110,7 @@ function M.level_value(level)
105110
end
106111
end
107112

113+
---@private
108114
function M.flush()
109115
if #M.entries == 0 then
110116
return

lua/render-markdown/core/node_info.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---@class render.md.NodeInfo
22
---@field private buf integer
3-
---@field node TSNode
3+
---@field private node TSNode
44
---@field type string
55
---@field text string
66
---@field start_row integer
@@ -38,6 +38,11 @@ function NodeInfo.__lt(a, b)
3838
end
3939
end
4040

41+
---@return TSNode
42+
function NodeInfo:get_node()
43+
return self.node
44+
end
45+
4146
---@return boolean
4247
function NodeInfo:has_error()
4348
return self.node:has_error()

lua/render-markdown/core/ui.lua

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ function M.get_row_marks(buf, win)
5151
assert(row ~= nil and hidden ~= nil, 'Row & range must be known to get marks')
5252

5353
local marks = {}
54-
for _, extmark in ipairs(buffer_state.marks or {}) do
54+
for _, extmark in ipairs(buffer_state:get_marks()) do
5555
if extmark:overlaps(hidden) then
56-
table.insert(marks, extmark.mark)
56+
table.insert(marks, extmark:get_mark())
5757
end
5858
end
5959
return row, marks
@@ -64,7 +64,7 @@ end
6464
---@param buffer_state render.md.BufferState
6565
function M.clear(buf, buffer_state)
6666
vim.api.nvim_buf_clear_namespace(buf, M.namespace, 0, -1)
67-
buffer_state.marks = nil
67+
buffer_state:set_marks(nil)
6868
end
6969

7070
---@param buf integer
@@ -109,13 +109,13 @@ function M.update(buf, win, parse)
109109
end
110110

111111
if next_state == 'rendered' then
112-
if buffer_state.marks == nil or parse then
112+
if not buffer_state:has_marks() or parse then
113113
M.clear(buf, buffer_state)
114-
buffer_state.marks = M.parse_buffer(buf, win)
114+
buffer_state:set_marks(M.parse_buffer(buf, win))
115115
end
116116
local hidden = config:hidden(mode, row)
117-
for _, extmark in ipairs(buffer_state.marks) do
118-
if extmark.mark.conceal and extmark:overlaps(hidden) then
117+
for _, extmark in ipairs(buffer_state:get_marks()) do
118+
if extmark:get_mark().conceal and extmark:overlaps(hidden) then
119119
extmark:hide(M.namespace, buf)
120120
else
121121
extmark:show(M.namespace, buf)
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
---@class render.md.debug.ValidatorSpec
2+
---@field private validator render.md.debug.Validator
3+
---@field private nilable? boolean
4+
---@field private suffix string
5+
---@field private input? table<string, any>
6+
---@field private opts table<string, vim.validate.Spec>
7+
local Spec = {}
8+
Spec.__index = Spec
9+
10+
---@param validator render.md.debug.Validator
11+
---@param path string
12+
---@param input table<string, any>
13+
---@param key? string|string[]
14+
---@param nilable? boolean
15+
---@return render.md.debug.ValidatorSpec
16+
function Spec.new(validator, path, input, key, nilable)
17+
local self = setmetatable({}, Spec)
18+
self.validator = validator
19+
self.nilable = nilable
20+
self.suffix = path
21+
self.input = input
22+
self.opts = {}
23+
if key ~= nil then
24+
key = type(key) == 'table' and key or { key }
25+
self.suffix = self.suffix .. '.' .. table.concat(key, '.')
26+
self.input = vim.tbl_get(self.input, unpack(key))
27+
assert(self.input ~= nil or self.nilable == true)
28+
end
29+
return self
30+
end
31+
32+
---@return string
33+
function Spec:get_suffix()
34+
return self.suffix
35+
end
36+
37+
---@return table<string, any>
38+
function Spec:get_input()
39+
return self.input
40+
end
41+
42+
---@param f fun(spec: render.md.debug.ValidatorSpec)
43+
---@param nilable? boolean
44+
function Spec:for_each(f, nilable)
45+
for name in pairs(self.input or {}) do
46+
f(Spec.new(self.validator, self.suffix, self.input, name, nilable))
47+
end
48+
end
49+
50+
---@param keys string|string[]
51+
---@param types type|type[]
52+
---@return render.md.debug.ValidatorSpec
53+
function Spec:type(keys, types)
54+
return self:add(keys, types, nil)
55+
end
56+
57+
---@param keys string|string[]
58+
---@param values string[]
59+
---@param input_types? type|type[]
60+
---@return render.md.debug.ValidatorSpec
61+
function Spec:one_of(keys, values, input_types)
62+
local types, suffix = self:handle_types(input_types)
63+
return self:add(keys, function(v)
64+
return vim.tbl_contains(values, v) or vim.tbl_contains(types, type(v))
65+
end, 'one of ' .. vim.inspect(values) .. suffix)
66+
end
67+
68+
---@param keys string|string[]
69+
---@param input_types? type|type[]
70+
---@return render.md.debug.ValidatorSpec
71+
function Spec:string_array(keys, input_types)
72+
local types, suffix = self:handle_types(input_types)
73+
return self:add(keys, function(v)
74+
if vim.tbl_contains(types, type(v)) then
75+
return true
76+
elseif type(v) == 'table' then
77+
for i, item in ipairs(v) do
78+
if type(item) ~= 'string' then
79+
return false, string.format('Index %d is %s', i, type(item))
80+
end
81+
end
82+
return true
83+
else
84+
return false
85+
end
86+
end, 'string array' .. suffix)
87+
end
88+
89+
---@param keys string|string[]
90+
---@param values string[]
91+
---@param input_types? type|type[]
92+
---@return render.md.debug.ValidatorSpec
93+
function Spec:one_or_array_of(keys, values, input_types)
94+
local types, suffix = self:handle_types(input_types)
95+
return self:add(keys, function(v)
96+
if vim.tbl_contains(types, type(v)) then
97+
return true
98+
elseif type(v) == 'string' then
99+
return vim.tbl_contains(values, v)
100+
elseif type(v) == 'table' then
101+
for i, item in ipairs(v) do
102+
if not vim.tbl_contains(values, item) then
103+
return false, string.format('Index %d is %s', i, item)
104+
end
105+
end
106+
return true
107+
else
108+
return false
109+
end
110+
end, 'one or array of ' .. vim.inspect(values) .. suffix)
111+
end
112+
113+
---@private
114+
---@param input_types? type|type[]
115+
---@return type[], string
116+
function Spec:handle_types(input_types)
117+
local types = nil
118+
if input_types == nil then
119+
types = {}
120+
elseif type(input_types) == 'string' then
121+
types = { input_types }
122+
else
123+
types = input_types
124+
end
125+
if self.nilable then
126+
table.insert(types, 'nil')
127+
end
128+
return types, #types == 0 and '' or (' or type ' .. vim.inspect(types))
129+
end
130+
131+
---@private
132+
---@param keys string|string[]
133+
---@param logic type|type[]|fun(v: any): boolean, any?
134+
---@param message string?
135+
---@return render.md.debug.ValidatorSpec
136+
function Spec:add(keys, logic, message)
137+
if self.input ~= nil then
138+
keys = type(keys) == 'table' and keys or { keys }
139+
for _, key in ipairs(keys) do
140+
---@diagnostic disable-next-line: assign-type-mismatch
141+
self.opts[key] = { self.input[key], logic, message or self.nilable }
142+
end
143+
end
144+
return self
145+
end
146+
147+
function Spec:check()
148+
if self.input ~= nil then
149+
self.validator:check(self.suffix, self.input, self.opts)
150+
end
151+
end
152+
153+
---@class render.md.debug.Validator
154+
---@field private prefix string
155+
---@field private errors string[]
156+
local Validator = {}
157+
Validator.__index = Validator
158+
159+
---@return render.md.debug.Validator
160+
function Validator.new()
161+
local self = setmetatable({}, Validator)
162+
self.prefix = 'render-markdown'
163+
self.errors = {}
164+
return self
165+
end
166+
167+
---@param path string
168+
---@param input table<string, any>
169+
---@param key? string|string[]
170+
---@param nilable? boolean
171+
---@return render.md.debug.ValidatorSpec
172+
function Validator:spec(path, input, key, nilable)
173+
return Spec.new(self, path, input, key, nilable)
174+
end
175+
176+
---@param suffix string
177+
---@param input table<string, any>
178+
---@param opts table<string, vim.validate.Spec>
179+
function Validator:check(suffix, input, opts)
180+
local path = self.prefix .. suffix
181+
local ok, err = pcall(vim.validate, opts)
182+
if not ok then
183+
table.insert(self.errors, path .. '.' .. err)
184+
end
185+
for key, _ in pairs(input) do
186+
if opts[key] == nil then
187+
table.insert(self.errors, string.format('%s.%s: is not a valid key', path, key))
188+
end
189+
end
190+
end
191+
192+
---@return string[]
193+
function Validator:get_errors()
194+
return self.errors
195+
end
196+
197+
return Validator

lua/render-markdown/health.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ local state = require('render-markdown.state')
44
local M = {}
55

66
---@private
7-
M.version = '7.1.6'
7+
M.version = '7.1.7'
88

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

lua/render-markdown/render/quote.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function Render:setup()
3131
end
3232

3333
function Render:render()
34-
self.context:query(self.info.node, state.markdown_quote_query, function(capture, info)
34+
self.context:query(self.info:get_node(), state.markdown_quote_query, function(capture, info)
3535
if capture == 'quote_marker' then
3636
self:quote_marker(info)
3737
else

0 commit comments

Comments
 (0)