Пређи на навигацију Пређи на претрагу
Документација модула[прикажи] [уреди] [историја] [освежи]

This module provides processing and checking of template arguments.


process(args, params, return_unknown)

Обрађује аргументе са датом листом параметара и враћа табелу која садржи обрађене аргументе. The args параметар одређује аргументе који се обрађују; они су аргументи из којих можете извућиframe:getParent().args. The params параметар одређује листу важећих параметара и састоји се од табеле. Ако се нађе неки аргумент који није у табели параметара, приказује се грешка.

Табела параметара треба да има имена параметара као индексе и (можда празну) таблицу ознака параметара као вредност. Празна табела као вредност само наводи да тај параметар постоји, али не би требао добити посебан третман. Следеће су наведене ознаке параметара.

Табела примера параметара (from Module:translations):

	[1] = {required = true, default = "und"},
	[2] = {},
	[3] = {list = true},
	["alt"] = {},
	["sc"] = {},
	["tr"] = {},

The return_unknown параметар, ако је подешен на true, спречава да функција изазове грешку када дође до аргумента са именом које не препознаје. Уместо тога, повратна вредност је пар вредности: први су обрађени аргументи као и обично, док други садрже све непознате аргументе који су остали необрађени. Ово вам омогућава да обављате вишестепену обраду, где цео скуп аргумената којег треба прихватити предложак није познат одједном. На пример, табела прелома може извршити неку генеричку обраду по неким аргументима, али онда одложи обраду остатка на функцију која се бави одређеним флескалним типом.

Parameter tags[уреди]

The parameter is required; an error is shown if it is not present. The template's page itself is an exception; no error is shown there.
Specifies a default value for the parameter, if it is absent or empty. When used on list parameters, this specifies a default value for the first item in the list only. Note that it is not possible to generate a default that depends on the value of other parameters.
If used together with required=true, the default applies only to the template's page itself. This can be used to show an example text.
Treat the parameter as an alias of another. When arguments are specified for this parameter, they will automatically be renamed and stored under the alias name. This allows for parameters with multiple alternative names, while still treating them as if they had only one name. It is even possible for the alias_of= to have a name that is not a parameter itself.
Aliases should not be required, as this prevents the other name or names of the parameter from being used. Parameters that are aliases and required at the same time are tracked (see Special:WhatLinksHere/Template:tracking/parameters/required alias).
If the argument is an empty string value, it is not converted to nil, but kept as-is.
Spacing characters such as spaces and newlines at the beginning and end of a positional parameter are not removed.
Specifies what value type to convert the argument into. The default is to leave it as a text string. Alternatives are:
The value is treated as a boolean value, either true or false. No value, the empty string, and the strings "0", "no", "n" and "false" are treated as false, all other values are considered true.
The value is converted into a number, unless it is nil.
Treat the parameter as a list of values, each having its own parameter name, rather than a single value. The parameters will have a number at the end, except for the first. For example, list=true on a parameter named "head" will include the parameters |head=, |head2=, |head3= and so on. If the parameter name is a number, another number doesn't get appended, but the counting simply continues, e.g. for parameter 3 the sequence is |3=, |4=, |5= etc. List parameters are returned as numbered lists, so for a template that is given the parameters head=a|head2=b|head3=c, the processed value of the parameter "head" will be {"a", "b", "c"}.
The value for list= can also be a string. This tells the module that parameters other than the first should have a different name, which is useful when the first parameter in a list is a number, but the remainder is named. An example would be for genders: list="g" on a parameter named 1 would have parameters |1=, |g2=, |g3= etc.
If the number is not located at the end, it can be specified by putting an equal sign "=" at the number position. For example, parameters "f1accel", "f2accel", ... can be captured by using the parameter name "f=accel", as is done in Module:headword/templates.
This is used in conjunction with list-type parameters. By default, the values are tightly packed in the resulting list. This means that if, for example, an entry specified head=a|head3=c but not |head2=, the returned list will be {"a", "c"}, with the values stored as index 1 and 2, not 1 and 3. If it is desirable to keep the numbering intact, for example if the numbers of several list parameters correlate with each other (like those of {{compound}}), then this tag can be specified.
If allow_holes=true is given, there may be nil values in between two real values, which makes many of Lua's table processing functions no longer work, like # or ipairs(). To remedy this, the resulting table will contain an additional named value, maxindex, which tells you the highest numeric index that is present in the table. In the example above, the resulting table will now be {"a", nil, "c", maxindex=3}. That way, you can iterate over the values from 1 to maxindex, while skipping nil values in between.

local export = {}

-- A helper function to escape magic characters in a string
-- Magic characters: ^$()%.[]*+-?
local plain = require("Module:string/pattern_escape")

-- A helper function that removes empty numeric indexes in a table,
-- so that the values are tightly packed like in a normal Lua table.
-- equivalent to require("Module:table").compressSparseArray
local function remove_holes(t)
	local ret = {}
	local index = 1
	local highest = 0
	for num, _ in pairs(t) do
		if type(num) == "number" and num > 0 and num < math.huge and math.floor(num) == num then
			highest = math.max(highest, num)
	for i = 1, highest do
		if t[i] then
			ret[index] = t[i]
			index = index + 1
	return ret

function export.process(args, params, return_unknown)
	local args_new = {}
	-- Process parameters for specific properties
	local required = {}
	local patterns = {}
	local names_with_equal_sign = {}
	local list_from_index = nil
	for name, param in pairs(params) do
		if param.required then
			if param.alias_of then
				require("Module:debug/track")("parameters/required alias")
			required[name] = true
		if param.list then
			local key = name
			if type(name) == "string" then
				key = string.gsub(name, "=", "")
			if param.default ~= nil then
				args_new[key] = {param.default, maxindex = 1}
				args_new[key] = {maxindex = 0}
			if type(param.list) == "string" then
				-- If the list property is a string, then it represents the name
				-- to be used as the prefix for list items. This is for use with lists
				-- where the first item is a numbered parameter and the
				-- subsequent ones are named, such as 1, pl2, pl3.
				if string.find(param.list, "=") then
					patterns["^" .. string.gsub(plain(param.list), "=", "(%%d+)") .. "$"] = name
					patterns["^" .. plain(param.list) .. "(%d+)$"] = name
			elseif type(name) == "number" then
				-- If the name is a number, then all indexed parameters from
				-- this number onwards go in the list.
				list_from_index = name
				if string.find(name, "=") then
					patterns["^" .. string.gsub(plain(name), "=", "(%%d+)") .. "$"] = string.gsub(name, "=", "")
					patterns["^" .. plain(name) .. "(%d+)$"] = name
			if string.find(name, "=") then
				-- Some elements may be skipped or processed twice if you do.
				-- Instead, track the changes we want to make to `params`, and
				-- do them after the iteration over `params` is done.
				table.insert(names_with_equal_sign, name)
		elseif param.default ~= nil then
			args_new[name] = param.default

	--Process required changes to `params`
	for _, name in ipairs(names_with_equal_sign) do
		require("Module:debug/track")("parameters/name with equals")
		params[string.gsub(name, "=", "")] = params[name]
		params[name] = nil

	-- Process the arguments
	local args_unknown = {}
	for name, val in pairs(args) do
		local index = nil
		if type(name) == "number" then
			if list_from_index ~= nil and name >= list_from_index then
				index = name - list_from_index + 1
				name = list_from_index
			-- Does this argument name match a pattern?
			for pattern, pname in pairs(patterns) do
				index = mw.ustring.match(name, pattern)
				-- It matches, so store the parameter name and the
				-- numeric index extracted from the argument name.
				if index then
					index = tonumber(index)
					name = pname
		local param = params[name]
		-- If a parameter without the trailing index was found, and
		-- require_index is set on the param, set the param to nil to treat it
		-- as if it isn't recognized.
		if not index and param and param.require_index then
			param = nil
		-- If no index was found, use 1 as the default index.
		-- This makes list parameters like g, g2, g3 put g at index 1.
		index = index or 1
		-- If the argument is not in the list of parameters, trigger an error.
		-- return_unknown suppresses the error, and stores it in a separate list instead.
		if not param then
			if return_unknown then
				args_unknown[name] = val
				error("The parameter \"" .. name .. "\" is not used by this template.", 2)
			-- Remove leading and trailing whitespace unless allow_whitespace is true.
			if not param.allow_whitespace then
				val = mw.text.trim(val)
			-- Empty string is equivalent to nil unless allow_empty is true.
			if val == "" and not param.allow_empty then
				val = nil
			-- Convert to proper type if necessary.
			if param.type == "boolean" then
				val = not (not val or val == "" or val == "0" or val == "no" or val == "n" or val == "false")
			elseif param.type == "number" then
				val = tonumber(val)
			elseif param.type then
				require("Module:debug/track") {
					"parameters/unrecognized type",
					"parameters/unrecognized type/" .. tostring(param.type)
			-- Can't use "if val" alone, because val may be a boolean false.
			if val ~= nil then
				-- Mark it as no longer required, as it is present.
				required[param.alias_of or name] = nil
				-- Store the argument value.
				if param.list then
					-- If the parameter is an alias of another, store it as the original,
					-- but avoid overwriting it; the original takes precedence.
					if not param.alias_of then
						args_new[name][index] = val
						-- Store the highest index we find.
						args_new[name].maxindex = math.max(index, args_new[name].maxindex)
					elseif args[param.alias_of] == nil then
						if params[param.alias_of] and params[param.alias_of].list then
							args_new[param.alias_of][index] = val
							-- Store the highest index we find.
							args_new[param.alias_of].maxindex = math.max(index, args_new[param.alias_of].maxindex)
							args_new[param.alias_of] = val
					-- If the parameter is an alias of another, store it as the original,
					-- but avoid overwriting it; the original takes precedence.
					if not param.alias_of then
						args_new[name] = val
					elseif args[param.alias_of] == nil then
						if params[param.alias_of] and params[param.alias_of].list then
							args_new[param.alias_of][1] = val
							-- Store the highest index we find.
							args_new[param.alias_of].maxindex = math.max(1, args_new[param.alias_of].maxindex)
							args_new[param.alias_of] = val
	-- The required table should now be empty.
	-- If any entry remains, trigger an error, unless we're in the template namespace.
	if mw.title.getCurrentTitle().nsText ~= "Template" then
		local list = {}
		for name, param in pairs(required) do
			table.insert(list, name)
		local count = #list
		if count == 1 then
			error('The parameter "' .. list[1] .. '" is required.', 2)
		elseif count == 2 then
			error('The parameters "' .. table.concat(list, '" and "') .. '" are required.', 2)
		elseif count > 2 then
			error('The parameters "' .. mw.text.listToText(list, '", "', '", and "') .. '" are required.', 2)
	-- Remove holes in any list parameters if needed.
	for name, val in pairs(args_new) do
		if type(val) == "table" and not params[name].allow_holes then
			args_new[name] = remove_holes(val)
	if return_unknown then
		return args_new, args_unknown
		return args_new

return export