Module:For params/sandbox
| This is the module sandbox page for Module:For params (diff). See also the companion subpage for test cases (run). |
| This module is rated as beta. It is considered ready for widespread use, but as it is still relatively new, it should be applied with some caution to ensure results are as expected. |
| This module depends on the following other modules: |
{{#invoke:For params|main}} implements a loop over valid numbered parameters. The loop body that receives the parameters is either defined as wikitext using |1= or as a template using |call=.
Syntax
[edit]- Wikitext:
{{#invoke:For params|main|<nowiki>wikitext<nowiki>|config parameters}} - Template:
{{#invoke:For params|main|call=template|config parameters}}
Body
[edit]The wikitext where parameters are substituted into is defined either as wikitext or a template. Parameters are passed with their number removed, i.e. |prefixisuffix= becomes |prefixsuffix= and |extraiextrasuffix= becomes |extraextrasuffix=. The parameter {{{i}}} is the current index, and {{{1}}} is the current unnamed parameter (if applicable).
- Body definition parameters
|1=- Wikitext to process using the parameters each iteration. Enclosed in<nowiki>...</nowiki>.|call=- Template to call. Overrides|1=. As with transclusion, if the passed title does have a namespace prefix, it will default to theTemplate:namespace.
Input
[edit]The parameters passed to the body are either prefix parameters, extra parameters, or fixed parameters.
- Parameter definitions parameters
|prefixn=- A parameter prefix to process. All registered parameter prefixes will be checked to determine if a iteration number is present in the provided arguments.|prefix1=defaults to processing unnamed parameters.|suffixn=- Suffix for the corresponding|prefixn=if applicable. For example,|prefix1=personwill look for parameters of the formpersonx(where x is a number), and|prefix1=person |suffix1=_namewill look for parameters of the formpersonx_name.|extran=- An extra parameter prefix to process. Unlike prefixes, these will not be checked to determine if a number is present in the provided arguments. For example, ifitemis a prefix andstyleis an extra, thenstyle2will be ignored unlessitem2is also defined.|extrasuffixn=- Suffix for the corresponding|extran=if applicable. For example,|extra1=agewill look for parameters of the formagex(where x is a number), and|extra1=person |suffix1=_agewill look for parameters of the formpersonx_age.|fixedn=- A fixed parameter to use the value of as an argument for all iterations. Useful for configuration parameters that apply to all iterations.
- Behaviour parameters
|sparse=- Set toyesto support parameter lists with gaps. Defaults tono.|optnum=- Whether or not to support passing the first parameter without a number, i.e. allow|prefixsuffix=rather than|prefix1suffix=for the first parameter. Defaults toyes.|start=- Begin iterating from this number. Parameters before this number are ignored.|noindex=- Don't pass{{{i}}}, the current index, to the body. Defaults tono, i.e. do pass{{{i}}}.
Concatenation
[edit]Before the final output is produced, optional concatenation separators can be added in-between iterations.
- Separator parameters
|sep=/|2=- Separator to add between outputs. To preserve leading and trailing whitespace, an unnamed parameter can be used instead (|2=, unless|call=is being used, then|1=).|conj=- Special separator to use before the final output. Outer spaces can be added with{{sp}}or .
Examples
[edit]Wkitext
[edit]Template wikitext:
{{#invoke:For params|main|<nowiki>{{{first}}} {{{last}}}</nowiki>|, |prefix1=last|prefix2=first}}
Template call:
{{__TEMPLATE__
|last1=Doe |first1=Jane
|last2=Smith |first2=John
}}
Output: Jane Doe, John Smith
When |optnum=no is not set, the first parameter set does not require a number suffix:
Template call:
{{__TEMPLATE__
|last=Doe |first=Jane
|last2=Smith |first2=John
|last3=White |first3=Walter
}}
Output: Jane Doe, John Smith, Walter White
If the first parameter set has a number suffix, parameters without a suffix are overridden:
Template call:
{{__TEMPLATE__
|last=Doe |first=Jane
|last1=Smith |first1=John
}}
Output: John Smith
If parameters specified some (but not all) prefixn are missing in a group, they will be missing in the call of the wikitext:
Template call:
{{__TEMPLATE__
|last1=Doe
|first2=John
}}
Output: {{{first}}} Doe, John {{{last}}}
Parameter suffixes
[edit]Template wikitext:
{{#invoke:For params|main|<nowiki>{{{person_name}}}, aged {{{person_age|?}}}</nowiki>|; |prefix=person|suffix=_name|extra=person|extrasuffix=age}}.
Template call:
{{__TEMPLATE__
|person_name=John |person_age=40
|person2_name=Jane |person2_age=45
|person3_name=Bill
}}
Output: John, aged 40; Jane, aged 45; Bill, aged ?.
Complex wikitext
[edit]Template wikitext:
{{#invoke:For params|main
|<nowiki>* ''{{{item}}}'' {{#if:{{{date|{{{alias|}}}}}}
| @ Date: {{#if:{{Yesno|{{{red_dates|}}}}}
| {{Red|{{{date|{{{alias|}}}}}}}}
| {{{date|{{{alias|}}}}}}
}}
}}</nowiki>|
|prefix1=item |extra1=date |extra2=alias |fixed1=bold_dates
}}
Template call:
{{__TEMPLATE__ |item1=Foo |item2=Bar |date2=2026-08-27 |item3=Baz |alias3=2026-08-30 |red_dates=1}}
Output:
- Foo
- Bar @ Date: 2026-08-27
- Baz @ Date: 2026-08-30
Secondary template
[edit]Template wikitext:
{{#invoke:For params|main |call=Cite web |prefix1=last |prefix2=first |prefix3=title |prefix4=url |noindex=y |sep={{sp}}}}
Template call:
{{__TEMPLATE__
|last=Doe |first=Jane |title=A website |url=https://www.example.com
|last2=Smith |first2=John |title2=A better website |url2=https://www.example.com/better
|last3=White |first3=Walter |title3=The best website |url3=https://www.example.com/best
}}
Output: Doe, Jane. "A website". Smith, John. "A better website". White, Walter. "The best website".
See also
[edit]local p = {}
local yesno = require('Module:Yesno')
-- Escape a string for inclusion in a Lua pattern
local function escPattern(s)
return s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1')
end
-- Get the value of a prefixed argument
local function getAffixedArg(args, prefix, suffix, num, optNum)
return args[prefix .. num .. suffix] or (num == 1 and optNum and args[prefix .. suffix]) or nil
end
-- Get parameters of type "typeName" from module arguments
local function getParams(args, typeName)
local params = {}
local i = 1
local cur = getAffixedArg(args, typeName, '', i, true)
while cur do
table.insert(params, cur)
i = i + 1
cur = getAffixedArg(args, typeName, '', i, true)
end
return params
end
-- Get suffixes of type "typeName" matching the provided prefixes
local function getSuffixes(args, typeName, prefixes)
local suffixes = {}
for i, _ in ipairs(prefixes) do
suffixes[i] = getAffixedArg(args, typeName, '', i, true) or ''
end
return suffixes
end
-- Return the function that processes each iteration
local function makeProcessor(frame, parent)
local noIndex = yesno(frame.args.noindex or false)
local template = frame.args.call
if template then
return function(num, args)
if not noIndex then args['i'] = num end
return frame:expandTemplate{title = template, args = args}
end
end
-- Note: The difference between angle brackets and their entities is lost
local code = mw.text.unstripNoWiki(frame.args[1]):gsub('<', '<'):gsub('>', '>')
return function(num, args)
if not noIndex then args['i'] = num end
return parent:newChild{title = 'Wikitext', args = args}:preprocess(code)
end
end
-- Create the argument iterator
local function numPairs(args, parentArgs, prefixes, suffixes, optNum)
local start = tonumber(args.start or 1)
-- Sparse mode
if yesno(args.sparse or false) then
local nums = {}
local foundAlready = {}
-- Check every argument to find prefixed arguments and numbers
for k, _ in pairs(parentArgs) do
-- Check every prefix for a match
for i, prefix in ipairs(prefixes) do
local numStr = tostring(k):match('^' .. escPattern(prefix) .. '(%d*)' .. escPattern(suffixes[i]) .. '$')
if numStr then
local num = tonumber(numStr) or optNum and 1 or nil
if num ~= nil and num >= start and not foundAlready[num] then
table.insert(nums, num)
foundAlready[num] = true
end
break
end
end
end
table.sort(nums)
-- Iterate over each found number
local function sequenceIter(a, i)
i = i + 1
if a[i] then return i, a[i] end
end
return sequenceIter, nums, 0
end
-- Iterate each number and check for any matches
local function prefixIter(a, i)
i = i + 1
-- Check every prefix for a match
for j, prefix in ipairs(prefixes) do
if getAffixedArg(a, prefix, suffixes[j], i, optNum) ~= nil then return i, i end
end
end
return prefixIter, parentArgs, start - 1
end
function p.main(frame)
local result = {}
local parent = frame:getParent()
local prefixes = getParams(frame.args, 'prefix')
-- Default to accepting unnamed parameters
if not prefixes[1] then prefixes[1] = '' end
local suffixes = getSuffixes(frame.args, 'suffix', prefixes)
local extras = getParams(frame.args, 'extra')
local extraSuffixes = getSuffixes(frame.args, 'extrasuffix', extras)
local fixeds = getParams(frame.args, 'fixed')
local process = makeProcessor(frame, parent)
local optNum = yesno(frame.args.optnum or true)
-- Iterate over each valid number
for _, num in numPairs(frame.args, parent.args, prefixes, suffixes, optNum) do
local args = {}
-- Pass registered fixed arguments
for _, fixed in ipairs(fixeds) do
args[fixed] = parent.args[fixed]
end
-- Pass extra parameters without their numeric component
for i, extra in ipairs(extras) do
local suffix = extraSuffixes[i]
args[extra .. suffix] = getAffixedArg(parent.args, extra, suffix, num, optNum)
end
-- Pass current parameters without their numeric component
for i, prefix in ipairs(prefixes) do
local suffix = suffixes[i]
local name = (prefix ~= '' or suffix ~= '') and prefix .. suffix or '1'
args[name] = getAffixedArg(parent.args, prefix, suffix, num, optNum)
end
table.insert(result, process(num, args))
end
-- Combine results using sep and conj
local sep = frame.args.call and frame.args[1] or frame.args[2] or frame.args.sep or ''
local conj = frame.args.conj or sep
return mw.text.listToText(result, sep, conj)
end
return p