Module:Sandbox/BrandonXLF/Module:Map params
Appearance
![]() | This module is rated as beta, and is ready for widespread use. It is still new and should be used with some caution to ensure the results are as expected. |
![]() | This module depends on the following other modules: |
{{#invoke:Map params|map}}
maps parameters received by a function to wikitext using |1=
or to a template call using |call=
.
Usage
{{#invoke:Map params|main|parameters}}
Parameters
Input
|prefixn=
- The prefix of the parameters to process. All registered prefixes will be checked to determine if a number is present in the provided arguments.|prefix1=
defaults to processing unnamed parameters.|extran=
- An extra parameter to pass to the wikitext or template being called. If the extra parameter is suffixed with a number (same as prefixed parameters but not checked to determine if a number is present), add the suffix(i)
. For example,style(i)
.|sparse=
- Set toyes
to support parameter lists with gaps. Defaults tono
.|optnum=
- Whether or not to support passing the first parameter without a number, i.e. allow it to be|prefix=
rather than|prefix1=
. Defaults toyes
.
Map to
|1=
- The wikitext to map parameters to. Parameters are substituted with their number removed, i.e.|itemn=
becomes|item=
etc. The parameter{{{i}}}
is replaced with the current index and{{{1}}}
is replaced with the current unnamed parameter (if applicable).|call=
- Template to call. Parameters are passed with their number removed, i.e.|itemn=
becomes|item=
etc. The parameter{{{i}}}
is the current index and{{{1}}}
is the current unnamed parameter (if applicable). Overrides|1=
.
Concatenation
|sep=
/|2=
- Separator to add between outputs. To preserve leading and tailing whitespace,|2=
can be used instead, or|1=
when|call=
is being used.|conj=
- Special separator to use before the final output. Outer spaces can be added with{{sp}}
or 
.
Advanced
|expand=
- Whether or not to expand templates, parser functions, extension tags, etc. after substituting parameters. This is most useful when|1=
is used without<nowiki>...</nowiki>
tags and can provide a slight performance advantage. Only relevant when using|1=
. Defaults toyes
.
See also
local p = {}
local yesno = require('Module:Yesno')
-- Escape a string to add to a Lua pattern
local function escPattern(s)
return s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1')
end
-- Get the prefixes to process
local function getPrefixes(args)
local prefixes = {}
local i = 1
repeat
table.insert(prefixes, args['prefix' .. i] or '')
i = i + 1
until not args['prefix' .. i]
return prefixes
end
-- Perform wikitext parameter substitution
function substParams(code, num, args)
local processed = code
:gsub("{{[iI]}}", num) -- Custom magic word {{I}}
:gsub("{{{([^{}|]*)|?[^{}]*}}}", args) -- Substitute parameters
return processed
end
-- Return the function that processes each iteration
function makeProcessor(frame)
local template = frame.args.call
if template then
return function(num, args)
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('>', '>')
local expand = yesno(frame.args.expand or true)
if expand then
return function(num, args)
return frame:preprocess(substParams(code, num, args))
end
end
return function(num, args)
return substParams(code, num, args)
end
end
function numPairs(args, parentArgs, prefixes)
local start = tonumber(args.start or 1)
if yesno(args.sparse or false) then
local nums = {}
local seenNums = {}
for k, _ in pairs(parentArgs) do
local prefixMatch = false
local j = 1
-- Check every prefix for a match
while prefixes[j] and not prefixMatch do
local numStr = tostring(k):match('^' .. escPattern(prefixes[j]) .. '([1-9]%d*)$')
if numStr then
local num = tonumber(numStr)
if num ~= nil and num >= start and not seenNums[num] then
table.insert(nums, num)
seenNums[num] = true
end
end
if numStr ~= nil then
prefixMatch = true
end
j = j + 1
end
end
table.sort(nums)
-- Iterate over each found number
function sequenceIter(a, i)
i = i + 1
local v = a[i]
if v then
return i, v
end
end
return sequenceIter, nums, 0
end
-- Iterate each number and check for any matches
local function prefixIter(a, i)
i = i + 1
local j = 1
local prefixMatch = false
-- Check every prefix for a match
while prefixes[j] and not prefixMatch do
prefixMatch = a[prefixes[j] .. i]
j = j + 1
end
if prefixMatch then
return i, i
end
end
return prefixIter, parentArgs, start - 1
end
function p.map(frame)
local result = {}
local parent = frame:getParent()
local sep = frame.args.sep or ''
local conj = frame.args.conj or sep
local prefixes = getPrefixes(frame.args)
local process = makeProcessor(frame)
for _, num in numPairs(frame.args, parent.args, prefixes) do
local args = {}
-- Inherent arguments passed to the template
for k, v in pairs(parent.args) do
args[k] = v
end
-- Pass current parameters without their numeric suffix
for _, prefix in ipairs(prefixes) do
args[prefix ~= '' and prefix or '@'] = parent.args[prefix ~= '' and prefix .. num or num]
end
table.insert(result, process(num, args))
end
return mw.text.listToText(result, sep, conj)
end
return p