Module:UtilsValidate: Difference between revisions

From Zelda Wiki, the Zelda encyclopedia
Jump to navigation Jump to search
mNo edit summary
No edit summary
 
(9 intermediate revisions by the same user not shown)
Line 15: Line 15:
})
})
local msg = i18n.getString(str, vars)
local msg = i18n.getString(str, vars)
local quiet = options and options.quiet
local stackTrace = options and options.stackTrace
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
if not quiet then
utilsError.warn(msg, stackTrace, 2)
utilsError.warn(msg, {
traceBack = stackTrace,
omitFrames = 2
})
end
end
return msg
return msg
Line 70: Line 84:
else
else
return s("msg.enumAccepted", {
return s("msg.enumAccepted", {
values = code(utilsTable.print(enum))
values = code(utilsTable.print(enum, true))
})
})
end
end
Line 87: Line 101:
end
end
for k, value in ipairs(values) do
for k, value in ipairs(values) do
value = mw.text.trim(value)
if not utilsTable.keyOf(acceptedValues, value) then
if not utilsTable.keyOf(acceptedValues, value) then
local path = utilsTable.concat(path or {}, multivalue and k or nil)
local path = utilsTable.concat(path or {}, multivalue and k or nil)
Line 98: Line 111:
end
end
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
end
end

Latest revision as of 01:38, 12 November 2020

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