Submodule for Module:UtilsArg and Module:UtilsSchema.
local p = {}
local i18n = require("Module:I18n")
local s = i18n.getString
local utilsError = require("Module:UtilsError")
local utilsTable = require("Module:UtilsTable")
local function code(s)
return string.format("<code>%s</code>", s)
end
local function err(str, name, path, options, vars)
vars = utilsTable.merge(vars or {}, {
path = code(name .. utilsTable.printPath(path))
})
local msg = i18n.getString(str, vars)
local options = options or {}
local quiet = options.quiet
local stackTrace = options.stackTrace
local isUsageError = options.isUsageError
if isUsageError then
local invokeFrameTitle = mw.getCurrentFrame():getParent():getTitle()
if mw.title.new(invokeFrameTitle).nsText == "Template" then
msg = string.format("Misuse of [[%s]]: %s", invokeFrameTitle, msg)
end
end
if not quiet then
utilsError.warn(msg, {
traceBack = stackTrace,
omitFrames = 2
})
end
return msg
end
function p.required(value, name, path, isKey, options)
if value == nil then
return err("msg.required", name, path, options)
end
end
function p.nonEmpty(value, name, path, isKey, options)
local isEmpty =
value == nil
or type(value) == "string" and value == ""
or type(value) == "table" and utilsTable.isEqual({}, value)
if isEmpty then
return err("msg.empty", name, path, options, {
actualValue = code(utilsTable.print(value))
})
end
end
function p.deprecated(value, name, path, isKey, options)
if value ~= nil then
return err("msg.deprecated", name, path, options, {
value = code(value)
})
end
end
function p.type(expectedType)
return function(value, name, path, isKey, options)
local actualType = type(value)
if value ~= nil and actualType ~= expectedType then
local msg = isKey and "msg.typeKey" or "msg.type"
return err(msg, name, path, options, {
expectedType = code(expectedType),
actualType = code(actualType),
key = isKey and code(tostring(value)) or nil,
})
end
end
end
local function enumDetails(enum)
if enum.reference then
return s("msg.enumReference", {
referencePage = enum.reference
})
else
return s("msg.enumAccepted", {
values = code(utilsTable.print(enum, true))
})
end
end
function p.enum(acceptedValues)
return function (value, name, path, isKey, options)
if type(acceptedValues) == "function" then
acceptedValues = acceptedValues()
end
-- Sometimes the argument is a list of values. It's easier to pretend that's always the case.
local values = value
local multivalue = type(value) == "table"
if not multivalue then
values = { value }
end
for k, value in ipairs(values) do
if not utilsTable.keyOf(acceptedValues, value) then
local path = utilsTable.concat(path or {}, multivalue and k or nil)
local msg = isKey and "msg.enumKey" or "msg.enum"
return err(msg, name, path, options, {
actualValue = code(value),
enumDetails = enumDetails(acceptedValues),
key = code(tostring(value)),
})
end
end
end
end
function p._enum(acceptedValues)
return function (value, name, path, isKey, options)
if type(acceptedValues) == "function" then
acceptedValues = acceptedValues()
end
-- Sometimes the argument is a list of values. It's easier to pretend that's always the case.
local values = value
local multivalue = type(value) == "table"
if not multivalue then
values = { value }
end
local errors = {}
for k, value in ipairs(values) do
if not utilsTable.keyOf(acceptedValues, value) then
local path = utilsTable.concat(path or {}, multivalue and k or nil)
local msg = isKey and "msg.enumKey" or "msg.enum"
table.insert(errors, err(msg, name, path, options, {
actualValue = code(value),
enumDetails = enumDetails(acceptedValues),
key = code(tostring(value)),
}))
end
end
return errors
end
end
i18n.loadStrings({
en = {
msg = {
empty = "${path} must be non-empty but is ${actualValue}.",
required = "${path} is required but is <code>nil</code>.",
type = "${path} is type ${actualType} but type ${expectedType} was expected.",
typeKey = "${path} key ${key} is type ${actualType} but type ${expectedType} was expected.",
deprecated = "${path} is deprecated but has value ${value}.",
enum = "${path} has unexpected value ${actualValue}. ${enumDetails}",
enumKey = "${key} is not an acceptable key for ${path}. ${enumDetails}",
enumAccepted = "The accepted values are: ${values}",
enumReference = "For a list of accepted values, refer to ${referencePage}.",
},
},
})
return p