وحدة:checkparams
يمكن إنشاء صفحة توثيق الوحدة في وحدة:checkparams/شرح
local m_str_utils = require("Module:string utilities")
local concat = table.concat
local error = error
local find_arguments = require("Module:template parser").findArguments
local format_categories = require("Module:utilities").format_categories
local gsplit = m_str_utils.gsplit
local gsub = string.gsub
local html_create = mw.html.create
local insert = table.insert
local match = string.match
local new_title = mw.title.new
local next = next
local pairs = pairs
local process_params = require("Module:parameters").process
local scribunto_param_key = m_str_utils.scribunto_param_key
local select = select
local sort = table.sort
local tostring = tostring
local type = type
local export = {}
local function get_template_title(frame)
return frame:getParent():getTitle()
end
local function get_template_content(frame)
return new_title(get_template_title(frame)):getContent()
end
local function get_allowed_args(frame)
-- returns a table of allowed args
local args = {}
-- first, detect all args used by the parent template
-- find_arguments takes the parent argument table as the second parameter so that argument names can be preprocessed, since these can vary based on the input if an argument name contains another argument (e.g. {{{foo{{{bar}}}baz}}})
for arg in find_arguments(get_template_content(frame), frame:getParent().args) do
args[arg] = {}
end
-- if frame.args[1] contains a comma separated list of param names, add those as well
local additional = frame.args[1]
if additional then
for arg in gsplit(additional, ",", true) do
-- scribunto_param_key normalizes the arg into the form returned by find_arguments (i.e. trimmed and converted to a number if appropriate)
arg = scribunto_param_key(arg)
if not args[arg] then
args[arg] = {}
end
end
end
return args
end
local function compare_params(a, b)
a, b = a[1], b[1]
local type_a = type(a)
if type_a == type(b) then
return a < b
end
return type_a == "number"
end
local function sort_params(invalid_args)
-- sort a table of parameters in the form {k, v}, sorting numbers before strings
local msg = {}
for k, v in pairs(invalid_args) do
insert(msg, {k, v})
end
sort(msg, compare_params)
for i = 1, #msg do
msg[i] = concat(msg[i], "=")
end
return msg
end
local function apply_pre_tag(frame, invalid_args)
return frame:extensionTag("pre", concat(invalid_args, "\n"))
end
local function make_message(template_name, invalid_args, no_link)
local open = no_link and "" or "[["
local close = no_link and "" or "]]"
return "The template " .. open .. template_name .. close .. " does not use the parameter(s): " .. invalid_args .. " Please see " .. open .. "Module:checkparams" .. close .. " for help with this warning."
end
local function make_warning_text(frame, template_name, invalid_args, nowarn, noattn, nocat)
-- generate "Invalid params" warning to be inserted into wiki page
-- template_name (required) name of the template with invalid params
-- invalid_args (required) table of invalid args
-- nocat= (optional) do not included category in warning_text
-- noattn= (optional) do not include attention seeking span in in warning_text
-- nowarn= (optional) do not include preview warning in warning_text
local warn, attn, cat
-- show warning in previewer
if not nowarn then
warn = tostring(html_create("sup")
:addClass("error")
:addClass("previewonly")
:tag("small")
:wikitext(make_message(template_name, apply_pre_tag(frame, invalid_args)))
:allDone())
end
-- add attentionseeking message
-- <pre> tags don't work in HTML attributes, so use semicolons as delimiters
if not noattn then
attn = tostring(html_create("span")
:addClass("attentionseeking")
:attr("title", make_message(template_name, concat(invalid_args, "; ") .. ".", "no_link"))
:allDone())
end
if not nocat then
cat = format_categories(
{"Pages using bad params when calling " .. template_name},
nil,
"-",
nil,
"force_output"
)
end
return (warn or "") .. (attn or "") .. (cat or "")
end
local function remove_placeholder_args(allowed_params, invalid_args)
-- some templates use params 1 and 3 without using 2,
-- which means that 2 will be in the list of invalid args
-- when used as an empty placeholder like in {{foo|1||3}}
-- this function will detect and remove any empty positionaly placeholder args
-- from a list of invalid_args
local max_pos = 0
for param in pairs(allowed_params) do
if type(param) == "number" and param > max_pos then
max_pos = param
end
end
for param in pairs(invalid_args) do
if (
type(param) == "number" and
param >= 1 and
param < max_pos and
not match(invalid_args[param], "[^%z\t-\v\r ]") -- charset used by MediaWiki to trim parameters
) then
invalid_args[param] = nil
end
end
end
function export.process(frame, allowed_params, nowarn, noattn, nocat)
-- This is desgined to be called by other Lua modules instead of calling Module:parameters.process()
-- frame - the frame containing the arguments to be checked
-- allowed_params - a table of valid arguments
-- nocat - if specified, will not included category in warning_text
-- noattn - if specified, will not include attention seeking span in in warning_text
-- nowarn - if specified, will not include preview warning in warning_text
-- returns valid_args, invalid_args, warning_text
local valid_args, invalid_args = process_params(
frame.args,
allowed_params,
"return unknown"
)
if next(invalid_args) then
remove_placeholder_args(allowed_params, invalid_args)
end
if next(invalid_args) then
local template_name = frame:getTitle()
return valid_args, invalid_args, make_warning_text(frame, template_name, sort_params(invalid_args), nowarn, noattn, nocat)
end
return valid_args, invalid_args, ""
end
function export.warn(frame)
-- This is designed to be called by non-Lua templates using "{{#invoke:checkparams|warn}}"
-- the passed frame is checked for the following params:
-- 1= (optional) a comma separated list of allowed parameters - if not specified, allows all parameters used as variables inside the template
-- nowarn= (optional) do not include preview warning in warning_text
-- noattn= (optional) do not include attention seeking span in in warning_text
-- nocat= (optional) do not included category in warning_text
local args = frame.args
return select(3, export.process(
frame:getParent(),
get_allowed_args(frame),
args.nowarn or false,
args.noattn or false,
args.nocat or false
))
end
do
local placeholder = "_message_"
function export.placeholder_error()
-- A dummy function that throws an error with a placeholder message.
error(placeholder, 0)
end
function export.error(frame)
-- This is designed to be called by non-Lua templates using "{{#invoke:checkparams|error}}"
-- the passed frame is checked for the following params:
-- 1= (optional) a comma separated list of allowed parameters - if not specified, allows all parameters used as variables inside the template
local allowed_args = get_allowed_args(frame)
local invalid_args = select(2, process_params(
frame:getParent().args,
allowed_args,
"return unknown"
))
if next(invalid_args) then
remove_placeholder_args(allowed_args, invalid_args)
end
-- Throw an error via callParserFunction, which generates a real error with traceback, automatic categorization in [[CAT:E]] etc., but the error message is returned as a string. Then, replace the placeholder error message with an error containing <pre> tags.
-- This is necessary because <pre> tags don't work in conventional error messages, so whitespace-related issues can't be shown accurately. Any whitespace which isn't trimmed is treated as literal, so errors caused by double-spaces or erroneous newlines in inputs need to be displayed accurately.
if next(invalid_args) then
return (gsub(
frame:callParserFunction("#invoke", "checkparams", "placeholder_error"),
placeholder,
make_message(get_template_title(frame), apply_pre_tag(frame, sort_params(invalid_args)))
))
end
end
end
return export