Edge Rewrite
// HTMLRewriter · presentation

This page was redesigned at the edge.

Cloudflare fetched the original article and streamed it through HTMLRewriter to apply an entirely new visual system without rebuilding the source page.

Jump to content

Module:Sandbox/BrandonXLF/Module:Map params

From Wikipedia, the free encyclopedia

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 value of a prefixed argument
function getPrefixedArg(args, prefix, num, optNum)
	return args[prefix .. num] or ((num == 1 and optNum and args[prefix]) or nil)
end

-- Get the prefixed parameters to process
local function getPrefixes(args)
	local prefixes = {}
    local i = 1
    local cur = getPrefixedArg(args, 'prefix', i, true)

    repeat
    	table.insert(prefixes, cur or '')
    	i = i + 1
    	cur = getPrefixedArg(args, 'prefix', i, true)
    until not cur
    
    return prefixes
end

-- Get the extra parameters to process
local function getExtras(args)
	local extras = {}
    local i = 1
    local cur = getPrefixedArg(args, 'extra', i, true)

    while cur do
    	local numMatch = cur:match('^(.+)%(i%)$')
    	
    	if numMatch then
    		table.insert(extras, {numMatch, true})
    	else
    		table.insert(extras, {cur, false})
    	end
    	
    	i = i + 1
    	cur = getPrefixedArg(args, 'extra', i, true)
    end
    
    return extras
end

-- Perform wikitext parameter substitution
function substParams(code, num, args)
	args['i'] = num
	local processed = code:gsub("{{{([^{}|]*)|?[^{}]*}}}", args) -- Substitute parameters
	return processed
end

-- Return the function that processes each iteration
function makeProcessor(frame, parent)
	local template = frame.args.call
	
	if template then
		return function(num, args)
			args['i'] = num
			
			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('&lt;', '<'):gsub('&gt;', '>')
	local expand = yesno(frame.args.expand or true)
	
	if expand then
		local processingFrame = parent:newChild{
			title = 'Module:Map params preprocessor',
			args = {}
		}
		
		return function(num, args)
			return processingFrame:preprocess(substParams(code, num, args))
		end
	end

	return function(num, args)
		return substParams(code, num, args)
	end
end

function numPairs(args, parentArgs, prefixes, optNum)
	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]) .. '(%d*)$')

	    		if numStr ~= nil then
	    			local num = tonumber(numStr) or (optNum and 1 or nil)

	    			if num ~= nil and num >= start and not seenNums[num] then
	    				table.insert(nums, num)
	    				seenNums[num] = true
	    			end

	    			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 = getPrefixedArg(a, prefixes[j], i, optNum) ~= nil
    		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.call and frame.args[1] or frame.args[2] or frame.args.sep or ''
	local conj = frame.args.conj or sep
	local prefixes = getPrefixes(frame.args)
	local extras = getExtras(frame.args)
	local process = makeProcessor(frame, parent)
	local optNum = yesno(frame.args.optnum or true)
	
	for _, num in numPairs(frame.args, parent.args, prefixes, optNum) do
		local args = {}
		
		-- Pass extra registered arguments
		for _, extraInfo in ipairs(extras) do
			local extra, numbered = unpack(extraInfo)
			
			if numbered then
				args[extra] = getPrefixedArg(parent.args, extra, num, optNum)
			else
				args[extra] = parent.args[extra]
			end
		end
		
		-- Pass current parameters without their numeric suffix
		for _, prefix in ipairs(prefixes) do
			args[prefix ~= '' and prefix or '1'] = getPrefixedArg(parent.args, prefix, num, optNum)
		end
		
		table.insert(result, process(num, args))
	end
	
	return mw.text.listToText(result, sep, conj)
end

return p