Skip to content

Commit d69a885

Browse files
feat: roll own type validation, removes reliance on vim.validate
## Details With the custom validator script we already had most things in place to remove the underlying usage of vim.validate. The main part of this change is in better handling of nested types and capturing non table values where tables are expected. Since vim.validate is changing in future releases of neovim this avoids any future required changes to support later versions.
1 parent 3da1bfc commit d69a885

File tree

6 files changed

+371
-296
lines changed

6 files changed

+371
-296
lines changed

CHANGELOG.md

+11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
## Pre-release
44

5+
### Features
6+
7+
- disabling background for code now keeps border [#220](https://github.com/MeanderingProgrammer/render-markdown.nvim/issues/220)
8+
[bee16b2](https://github.com/MeanderingProgrammer/render-markdown.nvim/commit/bee16b21bf47b64ceda8c9bb281d4b576d329c0f)
9+
- table support for all conceal levels [3da1bfc](https://github.com/MeanderingProgrammer/render-markdown.nvim/commit/3da1bfc4bd3a13fee57551f0b705ebcf2614d7a2)
10+
11+
### Bug Fixes
12+
13+
- padding & margin for code blocks indented with tabs [#230](https://github.com/MeanderingProgrammer/render-markdown.nvim/issues/230)
14+
[d80acb3](https://github.com/MeanderingProgrammer/render-markdown.nvim/commit/d80acb3f4ccc88052f65fa0a26e46c106b328bbe)
15+
516
## 7.5.0 (2024-11-04)
617

718
### Features

doc/render-markdown.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*render-markdown.txt* For 0.10.0 Last change: 2024 November 10
1+
*render-markdown.txt* For 0.10.0 Last change: 2024 November 11
22

33
==============================================================================
44
Table of Contents *render-markdown-table-of-contents*

lua/render-markdown/debug/validator.lua

+89-69
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1+
---@class render.md.debug.Spec
2+
---@field message string
3+
---@field validation fun(value: any): boolean, string?
4+
15
---@class render.md.debug.ValidatorSpec
26
---@field private validator render.md.debug.Validator
37
---@field private config? table<string, any>
48
---@field private nilable boolean
59
---@field private path string
6-
---@field private opts table<string, vim.validate.Spec>
10+
---@field private specs table<string, render.md.debug.Spec>
711
local Spec = {}
812
Spec.__index = Spec
913

1014
---@param validator render.md.debug.Validator
11-
---@param config table<string, any>
15+
---@param config? table<string, any>
1216
---@param nilable boolean
1317
---@param key? string|string[]
1418
---@param path? string
@@ -19,65 +23,68 @@ function Spec.new(validator, config, nilable, key, path)
1923
self.config = config
2024
self.nilable = nilable
2125
self.path = path or ''
22-
self.opts = {}
23-
if key ~= nil then
26+
self.specs = {}
27+
if self.config ~= nil and key ~= nil then
2428
key = type(key) == 'table' and key or { key }
2529
self.path = self.path .. '.' .. table.concat(key, '.')
2630
self.config = vim.tbl_get(self.config, unpack(key))
27-
assert(self.config ~= nil or self.nilable)
31+
self.config = type(self.config) == 'table' and self.config or nil
2832
end
2933
return self
3034
end
3135

32-
---@return string
33-
function Spec:get_path()
34-
return self.path
35-
end
36-
37-
---@return table<string, any>
38-
function Spec:get_config()
39-
return self.config
40-
end
41-
42-
---@param nilable boolean
36+
---@param keys 'ALL'|string|string[]
4337
---@param f fun(spec: render.md.debug.ValidatorSpec)
44-
function Spec:for_each(nilable, f)
45-
for name in pairs(self.config or {}) do
46-
local spec = Spec.new(self.validator, self.config, nilable, name, self.path)
47-
f(spec)
48-
spec:check()
38+
---@param nilable? boolean
39+
---@return render.md.debug.ValidatorSpec
40+
function Spec:nested(keys, f, nilable)
41+
if keys == 'ALL' then
42+
keys = self.config ~= nil and vim.tbl_keys(self.config) or {}
43+
else
44+
keys = type(keys) == 'table' and keys or { keys }
4945
end
46+
if nilable == nil then
47+
nilable = self.nilable
48+
end
49+
for _, key in ipairs(keys) do
50+
self:type(key, 'table')
51+
f(Spec.new(self.validator, self.config, nilable, key, self.path))
52+
end
53+
return self
5054
end
5155

5256
---@param keys string|string[]
53-
---@param types type|type[]
57+
---@param input_types type|type[]
5458
---@return render.md.debug.ValidatorSpec
55-
function Spec:type(keys, types)
56-
return self:add(keys, types, nil)
59+
function Spec:type(keys, input_types)
60+
local types, message = self:handle_types(input_types, '')
61+
return self:add(keys, message, function(value)
62+
return vim.tbl_contains(types, type(value))
63+
end)
5764
end
5865

5966
---@param keys string|string[]
6067
---@param values string[]
6168
---@param input_types? type|type[]
6269
---@return render.md.debug.ValidatorSpec
6370
function Spec:one_of(keys, values, input_types)
64-
local types, suffix = self:handle_types(input_types)
65-
return self:add(keys, function(v)
66-
return vim.tbl_contains(values, v) or vim.tbl_contains(types, type(v))
67-
end, 'one of ' .. vim.inspect(values) .. suffix)
71+
local types, message = self:handle_types(input_types, 'one of ' .. vim.inspect(values))
72+
return self:add(keys, message, function(value)
73+
return vim.tbl_contains(values, value) or vim.tbl_contains(types, type(value))
74+
end)
6875
end
6976

7077
---@param keys string|string[]
7178
---@param list_type type
7279
---@param input_types? type|type[]
7380
---@return render.md.debug.ValidatorSpec
7481
function Spec:list(keys, list_type, input_types)
75-
local types, suffix = self:handle_types(input_types)
76-
return self:add(keys, function(v)
77-
if vim.tbl_contains(types, type(v)) then
82+
local types, message = self:handle_types(input_types, list_type .. ' list')
83+
return self:add(keys, message, function(value)
84+
if vim.tbl_contains(types, type(value)) then
7885
return true
79-
elseif type(v) == 'table' then
80-
for i, item in ipairs(v) do
86+
elseif type(value) == 'table' then
87+
for i, item in ipairs(value) do
8188
if type(item) ~= list_type then
8289
return false, string.format('[%d] is %s', i, type(item))
8390
end
@@ -86,20 +93,20 @@ function Spec:list(keys, list_type, input_types)
8693
else
8794
return false
8895
end
89-
end, list_type .. ' list' .. suffix)
96+
end)
9097
end
9198

9299
---@param keys string|string[]
93100
---@param list_type type
94101
---@param input_types? type|type[]
95102
---@return render.md.debug.ValidatorSpec
96103
function Spec:list_or_list_of_list(keys, list_type, input_types)
97-
local types, suffix = self:handle_types(input_types)
98-
return self:add(keys, function(v)
99-
if vim.tbl_contains(types, type(v)) then
104+
local types, message = self:handle_types(input_types, list_type .. ' list or list of list')
105+
return self:add(keys, message, function(value)
106+
if vim.tbl_contains(types, type(value)) then
100107
return true
101-
elseif type(v) == 'table' then
102-
for i, item in ipairs(v) do
108+
elseif type(value) == 'table' then
109+
for i, item in ipairs(value) do
103110
if type(item) == 'table' then
104111
for j, nested in ipairs(item) do
105112
if type(nested) ~= list_type then
@@ -114,22 +121,22 @@ function Spec:list_or_list_of_list(keys, list_type, input_types)
114121
else
115122
return false
116123
end
117-
end, list_type .. ' list or list of list' .. suffix)
124+
end)
118125
end
119126

120127
---@param keys string|string[]
121128
---@param values string[]
122129
---@param input_types? type|type[]
123130
---@return render.md.debug.ValidatorSpec
124131
function Spec:one_or_list_of(keys, values, input_types)
125-
local types, suffix = self:handle_types(input_types)
126-
return self:add(keys, function(v)
127-
if vim.tbl_contains(types, type(v)) then
132+
local types, message = self:handle_types(input_types, 'one or list of ' .. vim.inspect(values))
133+
return self:add(keys, message, function(value)
134+
if vim.tbl_contains(types, type(value)) then
128135
return true
129-
elseif type(v) == 'string' then
130-
return vim.tbl_contains(values, v)
131-
elseif type(v) == 'table' then
132-
for i, item in ipairs(v) do
136+
elseif type(value) == 'string' then
137+
return vim.tbl_contains(values, value)
138+
elseif type(value) == 'table' then
139+
for i, item in ipairs(value) do
133140
if not vim.tbl_contains(values, item) then
134141
return false, string.format('[%d] is %s', i, item)
135142
end
@@ -138,13 +145,14 @@ function Spec:one_or_list_of(keys, values, input_types)
138145
else
139146
return false
140147
end
141-
end, 'one or list of ' .. vim.inspect(values) .. suffix)
148+
end)
142149
end
143150

144151
---@private
145152
---@param input_types? type|type[]
153+
---@param prefix string
146154
---@return type[], string
147-
function Spec:handle_types(input_types)
155+
function Spec:handle_types(input_types, prefix)
148156
local types = nil
149157
if input_types == nil then
150158
types = {}
@@ -156,33 +164,36 @@ function Spec:handle_types(input_types)
156164
if self.nilable and not vim.tbl_contains(types, 'nil') then
157165
table.insert(types, 'nil')
158166
end
159-
return types, #types == 0 and '' or (' or type ' .. vim.inspect(types))
167+
local message = prefix
168+
if #types > 0 then
169+
if #message > 0 then
170+
message = message .. ' or '
171+
end
172+
message = message .. 'type ' .. table.concat(types, ' or ')
173+
end
174+
return types, message
160175
end
161176

162177
---@private
163178
---@param keys string|string[]
164-
---@param logic type|type[]|fun(v: any): boolean, any?
165-
---@param message string?
179+
---@param message string
180+
---@param validation fun(v: any): boolean, string?
166181
---@return render.md.debug.ValidatorSpec
167-
function Spec:add(keys, logic, message)
182+
function Spec:add(keys, message, validation)
168183
if self.config ~= nil then
169184
keys = type(keys) == 'table' and keys or { keys }
170185
for _, key in ipairs(keys) do
171-
---@diagnostic disable-next-line: assign-type-mismatch
172-
self.opts[key] = { self.config[key], logic, message or self.nilable }
186+
self.specs[key] = { message = message, validation = validation }
173187
end
174188
end
175189
return self
176190
end
177191

178192
function Spec:check()
179-
if self.config == nil then
193+
if self.config == nil or vim.tbl_count(self.specs) == 0 then
180194
return
181195
end
182-
if vim.tbl_count(self.opts) == 0 then
183-
return
184-
end
185-
self.validator:check(self.path, self.config, self.opts)
196+
self.validator:check(self.path, self.config, self.specs)
186197
end
187198

188199
---@class render.md.debug.Validator
@@ -201,24 +212,33 @@ end
201212

202213
Validator.spec = Spec.new
203214

204-
---@param suffix string
215+
---@param path string
205216
---@param config table<string, any>
206-
---@param opts table<string, vim.validate.Spec>
207-
function Validator:check(suffix, config, opts)
208-
local path = self.prefix .. suffix
209-
local ok, err = pcall(vim.validate, opts)
210-
if not ok then
211-
table.insert(self.errors, path .. '.' .. err)
217+
---@param specs table<string, render.md.debug.Spec>
218+
function Validator:check(path, config, specs)
219+
path = self.prefix .. path
220+
for key, spec in pairs(specs) do
221+
local value = config[key]
222+
local ok, info = spec.validation(value)
223+
if not ok then
224+
local message = string.format('%s.%s: expected %s, got %s', path, key, spec.message, type(value))
225+
if info ~= nil then
226+
message = message .. string.format(', info: %s', info)
227+
end
228+
table.insert(self.errors, message)
229+
end
212230
end
213231
for key, _ in pairs(config) do
214-
if opts[key] == nil then
215-
table.insert(self.errors, string.format('%s.%s: is not a valid key', path, key))
232+
if specs[key] == nil then
233+
local message = string.format('%s.%s: is not a valid key', path, key)
234+
table.insert(self.errors, message)
216235
end
217236
end
218237
end
219238

220239
---@return string[]
221240
function Validator:get_errors()
241+
table.sort(self.errors)
222242
return self.errors
223243
end
224244

lua/render-markdown/health.lua

+1-1
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.5.3'
7+
M.version = '7.5.4'
88

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

0 commit comments

Comments
 (0)