<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="https://wiki.besa.de/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://wiki.besa.de/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mr.+Stradivarius+on+tour</id>
		<title>BESA® Wiki - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="https://wiki.besa.de/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mr.+Stradivarius+on+tour"/>
		<link rel="alternate" type="text/html" href="https://wiki.besa.de/index.php?title=Special:Contributions/Mr._Stradivarius_on_tour"/>
		<updated>2026-05-05T08:46:53Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.23.10</generator>

	<entry>
		<id>https://wiki.besa.de/index.php?title=Module:TableTools</id>
		<title>Module:TableTools</title>
		<link rel="alternate" type="text/html" href="https://wiki.besa.de/index.php?title=Module:TableTools"/>
				<updated>2013-12-17T07:39:19Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius on tour: check type of prefix and suffix&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--                               TableTools                                       --&lt;br /&gt;
--                                                                                --&lt;br /&gt;
-- This module includes a number of functions for dealing with Lua tables.        --&lt;br /&gt;
-- It is a meta-module, meant to be called from other Lua modules, and should     --&lt;br /&gt;
-- not be called directly from #invoke.                                           --&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
local libraryUtil = require('libraryUtil')&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Define often-used variables and functions.&lt;br /&gt;
local floor = math.floor&lt;br /&gt;
local infinity = math.huge&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
&lt;br /&gt;
-- Define a unique value to represent NaN. This is because NaN cannot be used as a table key.&lt;br /&gt;
local nan = {}&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- isPositiveInteger&lt;br /&gt;
--&lt;br /&gt;
-- This function returns true if the given number is a positive integer, and false&lt;br /&gt;
-- if not. Although it doesn't operate on tables, it is included here as it is&lt;br /&gt;
-- useful for determining whether a given table key is in the array part or the&lt;br /&gt;
-- hash part of a table.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.isPositiveInteger(num)&lt;br /&gt;
	if type(num) == 'number' and num &amp;gt;= 1 and floor(num) == num and num &amp;lt; infinity then&lt;br /&gt;
		return true&lt;br /&gt;
	else&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- union&lt;br /&gt;
--&lt;br /&gt;
-- This returns the union of the key/value pairs of n tables. If any of the tables&lt;br /&gt;
-- contain different values for the same table key, the table value is converted&lt;br /&gt;
-- to an array holding all of the different values.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.union(...)&lt;br /&gt;
	local ret, trackArrays = {}, {}&lt;br /&gt;
	for i = 1, select('#', ...) do&lt;br /&gt;
		local t = select(i, ...)&lt;br /&gt;
		checkType('union', i, t, 'table')&lt;br /&gt;
		for k, v in pairs(t) do&lt;br /&gt;
			local retKey = ret[k]&lt;br /&gt;
			if retKey == nil then&lt;br /&gt;
				ret[k] = v&lt;br /&gt;
			elseif retKey ~= v then&lt;br /&gt;
				if trackArrays[k] then&lt;br /&gt;
					local array = ret[k]&lt;br /&gt;
					local valExists&lt;br /&gt;
					for _, arrayVal in ipairs(array) do&lt;br /&gt;
						if arrayVal == v then&lt;br /&gt;
							valExists = true&lt;br /&gt;
							break&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
					if not valExists then&lt;br /&gt;
						array[#array + 1] = v&lt;br /&gt;
						ret[k] = array&lt;br /&gt;
					end&lt;br /&gt;
				else&lt;br /&gt;
					ret[k] = {ret[k], v}&lt;br /&gt;
					trackArrays[k] = true&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end				&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- valueUnion&lt;br /&gt;
--&lt;br /&gt;
-- This returns the union of the values of n tables, as an array. For example, for&lt;br /&gt;
-- the tables {1, 3, 4, 5, foo = 7} and {2, bar = 3, 5, 6}, union will return&lt;br /&gt;
-- {1, 2, 3, 4, 5, 6, 7}.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.valueUnion(...)&lt;br /&gt;
	local vals, ret = {}, {}&lt;br /&gt;
	for i = 1, select('#', ...) do&lt;br /&gt;
		local t = select(i, ...)&lt;br /&gt;
		checkType('valueUnion', i, t, 'table')&lt;br /&gt;
		for k, v in pairs(t) do&lt;br /&gt;
			if type(v) == 'number' and tostring(v) == '-nan' then&lt;br /&gt;
				v = nan -- NaN cannot be a table key, so use a proxy variable.&lt;br /&gt;
			end&lt;br /&gt;
			vals[v] = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	for val in pairs(vals) do&lt;br /&gt;
		if val == nan then&lt;br /&gt;
			-- This ensures that we output a NaN when we had one as input, although&lt;br /&gt;
			-- they may have been generated in a completely different way.&lt;br /&gt;
			val = 0/0 &lt;br /&gt;
		end&lt;br /&gt;
		ret[#ret + 1] = val&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end	&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- intersection&lt;br /&gt;
--&lt;br /&gt;
-- This returns the intersection of the key/value pairs of n tables. Both the key&lt;br /&gt;
-- and the value must match to be included in the resulting table.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.intersection(...)&lt;br /&gt;
	local ret, track, pairCounts = {}, {}, {}&lt;br /&gt;
	local lim = select('#', ...)&lt;br /&gt;
	for i = 1, lim do&lt;br /&gt;
		local t = select(i, ...)&lt;br /&gt;
		checkType('intersection', i, t, 'table')&lt;br /&gt;
		for k, v in pairs(t) do&lt;br /&gt;
			local trackVal = track[k]&lt;br /&gt;
			if trackVal == nil then&lt;br /&gt;
				track[k] = v&lt;br /&gt;
				pairCounts[k] = 1&lt;br /&gt;
			elseif trackVal == v then&lt;br /&gt;
				pairCounts[k] = pairCounts[k] + 1&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	for k, v in pairs(track) do&lt;br /&gt;
		if pairCounts[k] == lim then&lt;br /&gt;
			ret[k] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- valueIntersection&lt;br /&gt;
--&lt;br /&gt;
-- This returns the intersection of the values of n tables, as an array. For&lt;br /&gt;
-- example, for the tables {1, 3, 4, 5, foo = 7} and {2, bar = 3, 5, 6}, &lt;br /&gt;
-- intersection will return {3, 5}.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.valueIntersection(...)&lt;br /&gt;
	local vals, ret = {}, {}&lt;br /&gt;
	local lim = select('#', ...)&lt;br /&gt;
	for i = 1, lim do&lt;br /&gt;
		local t = select(i, ...)&lt;br /&gt;
		checkType('valueIntersection', i, t, 'table')&lt;br /&gt;
		for k, v in pairs(t) do&lt;br /&gt;
			if type(v) == 'number' and tostring(v) == '-nan' then&lt;br /&gt;
				v = nan -- NaN cannot be a table key, so use a proxy variable.&lt;br /&gt;
			end&lt;br /&gt;
			local valCount = vals[v] or 0&lt;br /&gt;
			vals[v] = valCount + 1&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	for val, count in pairs(vals) do&lt;br /&gt;
		if count == lim then&lt;br /&gt;
			if val == nan then&lt;br /&gt;
				-- This ensures that we output a NaN when we had one as input, although&lt;br /&gt;
				-- they may have been generated in a completely different way.&lt;br /&gt;
				val = 0/0 &lt;br /&gt;
			end&lt;br /&gt;
			ret[#ret + 1] = val&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- numKeys&lt;br /&gt;
--&lt;br /&gt;
-- This takes a table and returns an array containing the numbers of any numerical&lt;br /&gt;
-- keys that have non-nil values, sorted in numerical order.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.numKeys(t)&lt;br /&gt;
	checkType('numKeys', 1, t, 'table')&lt;br /&gt;
	local isPositiveInteger = p.isPositiveInteger&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		if isPositiveInteger(k) then&lt;br /&gt;
			nums[#nums + 1] = k&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(nums)&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- affixNums&lt;br /&gt;
--&lt;br /&gt;
-- This takes a table and returns an array containing the numbers of keys with the&lt;br /&gt;
-- specified prefix and suffix. For example, for the table&lt;br /&gt;
-- {a1 = 'foo', a3 = 'bar', a6 = 'baz'} and the prefix &amp;quot;a&amp;quot;, affixNums will&lt;br /&gt;
-- return {1, 3, 6}.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.affixNums(t, prefix, suffix)&lt;br /&gt;
	checkType('affixNums', 1, t, 'table')&lt;br /&gt;
	checkType('affixNums', 2, prefix, 'string', true)&lt;br /&gt;
	checkType('affixNums', 3, suffix, 'string', true)&lt;br /&gt;
	prefix = prefix or ''&lt;br /&gt;
	suffix = suffix or ''&lt;br /&gt;
	local pattern = '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$'&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		if type(k) == 'string' then			&lt;br /&gt;
			local num = mw.ustring.match(k, pattern)&lt;br /&gt;
			if num then&lt;br /&gt;
				nums[#nums + 1] = tonumber(num)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(nums)&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- compressSparseArray&lt;br /&gt;
--&lt;br /&gt;
-- This takes an array with one or more nil values, and removes the nil values&lt;br /&gt;
-- while preserving the order, so that the array can be safely traversed with&lt;br /&gt;
-- ipairs.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.compressSparseArray(t)&lt;br /&gt;
	checkType('compressSparseArray', 1, t, 'table')&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	local nums = p.numKeys(t)&lt;br /&gt;
	for _, num in ipairs(nums) do&lt;br /&gt;
		ret[#ret + 1] = t[num]&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- sparseIpairs&lt;br /&gt;
--&lt;br /&gt;
-- This is an iterator for sparse arrays. It can be used like ipairs, but can&lt;br /&gt;
-- handle nil values.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.sparseIpairs(t)&lt;br /&gt;
	checkType('sparseIpairs', 1, t, 'table')&lt;br /&gt;
	local nums = p.numKeys(t)&lt;br /&gt;
	local i = 0&lt;br /&gt;
	local lim = #nums&lt;br /&gt;
	return function ()&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		if i &amp;lt;= lim then&lt;br /&gt;
			local key = nums[i]&lt;br /&gt;
			return key, t[key]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- size&lt;br /&gt;
--&lt;br /&gt;
-- This returns the size of a key/value pair table. It will also work on arrays,&lt;br /&gt;
-- but for arrays it is more efficient to use the # operator.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.size(t)&lt;br /&gt;
	checkType('size', 1, t, 'table')&lt;br /&gt;
	local i = 0&lt;br /&gt;
	for k in pairs(t) do&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return i&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius on tour</name></author>	</entry>

	<entry>
		<id>https://wiki.besa.de/index.php?title=Module:Message_box</id>
		<title>Module:Message box</title>
		<link rel="alternate" type="text/html" href="https://wiki.besa.de/index.php?title=Module:Message_box"/>
				<updated>2013-10-08T01:58:55Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius on tour: make args.all work&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This is a meta-module for producing message box templates, including {{mbox}}, {{ambox}}, {{imbox}}, {{tmbox}}, {{ombox}}, {{cmbox}} and {{fmbox}}.&lt;br /&gt;
&lt;br /&gt;
-- Require necessary modules.&lt;br /&gt;
local htmlBuilder = require('Module:HtmlBuilder')&lt;br /&gt;
local categoryHandler = require('Module:Category handler').main&lt;br /&gt;
local yesno = require('Module:Yesno')&lt;br /&gt;
&lt;br /&gt;
-- Load the configuration page.&lt;br /&gt;
local cfgTables = mw.loadData('Module:Message box/configuration')&lt;br /&gt;
&lt;br /&gt;
-- Get a language object for formatDate and ucfirst.&lt;br /&gt;
local lang = mw.language.getContentLanguage()&lt;br /&gt;
&lt;br /&gt;
-- Set aliases for often-used functions to reduce table lookups.&lt;br /&gt;
local format = mw.ustring.format&lt;br /&gt;
local tinsert = table.insert&lt;br /&gt;
local tconcat = table.concat&lt;br /&gt;
local trim = mw.text.trim&lt;br /&gt;
&lt;br /&gt;
local box = {}&lt;br /&gt;
&lt;br /&gt;
local function getTitleObject(page)&lt;br /&gt;
    if type(page) == 'string' then&lt;br /&gt;
        -- Get the title object, passing the function through pcall &lt;br /&gt;
        -- in case we are over the expensive function count limit.&lt;br /&gt;
        local success, title = pcall(mw.title.new, page)&lt;br /&gt;
        if success then&lt;br /&gt;
            return title&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function union(t1, t2)&lt;br /&gt;
    -- Returns the union of two arrays.&lt;br /&gt;
    local vals = {}&lt;br /&gt;
    for i, v in ipairs(t1) do&lt;br /&gt;
        vals[v] = true&lt;br /&gt;
    end&lt;br /&gt;
    for i, v in ipairs(t2) do&lt;br /&gt;
        vals[v] = true&lt;br /&gt;
    end&lt;br /&gt;
    local ret = {}&lt;br /&gt;
    for k in pairs(vals) do&lt;br /&gt;
        tinsert(ret, k)&lt;br /&gt;
    end&lt;br /&gt;
    table.sort(ret)&lt;br /&gt;
    return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getArgNums(args, prefix)&lt;br /&gt;
    local nums = {}&lt;br /&gt;
    for k, v in pairs(args) do&lt;br /&gt;
        local num = mw.ustring.match(tostring(k), '^' .. prefix .. '([1-9]%d*)$')&lt;br /&gt;
        if num then&lt;br /&gt;
            tinsert(nums, tonumber(num))&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    table.sort(nums)&lt;br /&gt;
    return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box.getNamespaceId(ns)&lt;br /&gt;
    if not ns then return end&lt;br /&gt;
    if type(ns) == 'string' then&lt;br /&gt;
        ns = lang:ucfirst(mw.ustring.lower(ns))&lt;br /&gt;
        if ns == 'Main' then&lt;br /&gt;
            ns = 0&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    local nsTable = mw.site.namespaces[ns]&lt;br /&gt;
    if nsTable then&lt;br /&gt;
        return nsTable.id&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box.getMboxType(nsid)&lt;br /&gt;
    -- Gets the mbox type from a namespace number.&lt;br /&gt;
    if nsid == 0 then&lt;br /&gt;
        return 'ambox' -- main namespace&lt;br /&gt;
    elseif nsid == 6 then&lt;br /&gt;
        return 'imbox' -- file namespace&lt;br /&gt;
    elseif nsid == 14 then&lt;br /&gt;
        return 'cmbox' -- category namespace&lt;br /&gt;
    else&lt;br /&gt;
        local nsTable = mw.site.namespaces[nsid]&lt;br /&gt;
        if nsTable and nsTable.isTalk then&lt;br /&gt;
            return 'tmbox' -- any talk namespace&lt;br /&gt;
        else&lt;br /&gt;
            return 'ombox' -- other namespaces or invalid input&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box:addCat(ns, cat, sort)&lt;br /&gt;
    if type(cat) ~= 'string' then return end&lt;br /&gt;
    local nsVals = {'main', 'template', 'all'}&lt;br /&gt;
    local tname&lt;br /&gt;
    for i, val in ipairs(nsVals) do&lt;br /&gt;
        if ns == val then&lt;br /&gt;
            tname = ns .. 'Cats'&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if not tname then&lt;br /&gt;
        for i, val in ipairs(nsVals) do&lt;br /&gt;
            nsVals[i] = format('&amp;quot;%s&amp;quot;', val)&lt;br /&gt;
        end&lt;br /&gt;
        error('invalid ns parameter passed to box:addCat; valid values are ' .. mw.text.listToText(nsVals, nil, ' or '))&lt;br /&gt;
    end&lt;br /&gt;
    self[tname] = self[tname] or {}&lt;br /&gt;
    if type(sort) == 'string' then&lt;br /&gt;
        tinsert(self[tname], format('[[Category:%s|%s]]', cat, sort))&lt;br /&gt;
    else&lt;br /&gt;
        tinsert(self[tname], format('[[Category:%s]]', cat))&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box:addClass(class)&lt;br /&gt;
    if type(class) ~= 'string' then return end&lt;br /&gt;
    self.classes = self.classes or {}&lt;br /&gt;
    tinsert(self.classes, class)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box:setTitle(args)&lt;br /&gt;
    -- Get the title object and the namespace.&lt;br /&gt;
    self.pageTitle = getTitleObject(args.page ~= '' and args.page)&lt;br /&gt;
    self.title = self.pageTitle or mw.title.getCurrentTitle()&lt;br /&gt;
    self.demospace = args.demospace ~= '' and args.demospace or nil&lt;br /&gt;
    self.nsid = box.getNamespaceId(self.demospace) or self.title.namespace&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box:getConfig(boxType)&lt;br /&gt;
    -- Get the box config data from the data page.&lt;br /&gt;
    if boxType == 'mbox' then&lt;br /&gt;
        boxType = box.getMboxType(self.nsid)&lt;br /&gt;
    end&lt;br /&gt;
    local cfg = cfgTables[boxType]&lt;br /&gt;
    if not cfg then&lt;br /&gt;
        local boxTypes = {}&lt;br /&gt;
        for k, v in pairs(dataTables) do&lt;br /&gt;
            tinsert(boxTypes, format('&amp;quot;%s&amp;quot;', k))&lt;br /&gt;
        end&lt;br /&gt;
        tinsert(boxTypes, '&amp;quot;mbox&amp;quot;')&lt;br /&gt;
        error(format('invalid message box type &amp;quot;%s&amp;quot;; valid types are %s', tostring(boxType), mw.text.listToText(boxTypes)), 2)&lt;br /&gt;
    end&lt;br /&gt;
    return cfg&lt;br /&gt;
end&lt;br /&gt;
    &lt;br /&gt;
function box:removeBlankArgs(cfg, args)&lt;br /&gt;
    -- Only allow blank arguments for the parameter names listed in cfg.allowBlankParams.&lt;br /&gt;
    local newArgs = {}&lt;br /&gt;
    for k, v in pairs(args) do&lt;br /&gt;
        if v ~= '' then&lt;br /&gt;
            newArgs[k] = v&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    for i, param in ipairs(cfg.allowBlankParams or {}) do&lt;br /&gt;
        newArgs[param] = args[param]&lt;br /&gt;
    end&lt;br /&gt;
    return newArgs&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box:setBoxParameters(cfg, args)&lt;br /&gt;
    -- Get type data.&lt;br /&gt;
    self.type = args.type&lt;br /&gt;
    local typeData = cfg.types[self.type]&lt;br /&gt;
    self.invalidTypeError = cfg.showInvalidTypeError and self.type and not typeData and true or false&lt;br /&gt;
    typeData = typeData or cfg.types[cfg.default]&lt;br /&gt;
    self.typeClass = typeData.class&lt;br /&gt;
    self.typeImage = typeData.image&lt;br /&gt;
&lt;br /&gt;
    -- Find if the box has been wrongly substituted.&lt;br /&gt;
    if cfg.substCheck and args.subst == 'SUBST' then&lt;br /&gt;
        self.isSubstituted = true&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Find whether we are using a small message box.&lt;br /&gt;
    if cfg.allowSmall and (&lt;br /&gt;
            cfg.smallParam and args.small == cfg.smallParam&lt;br /&gt;
            or not cfg.smallParam and yesno(args.small)&lt;br /&gt;
    )&lt;br /&gt;
    then&lt;br /&gt;
        self.isSmall = true&lt;br /&gt;
    else&lt;br /&gt;
        self.isSmall = false&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Add attributes, classes and styles.&lt;br /&gt;
    self.id = args.id&lt;br /&gt;
    self:addClass(cfg.usePlainlinksParam and yesno(args.plainlinks or true) and 'plainlinks')&lt;br /&gt;
    for _, class in ipairs(cfg.classes or {}) do&lt;br /&gt;
        self:addClass(class)&lt;br /&gt;
    end&lt;br /&gt;
    if self.isSmall then&lt;br /&gt;
        self:addClass(cfg.smallClass or 'mbox-small')&lt;br /&gt;
    end&lt;br /&gt;
    self:addClass(self.typeClass)&lt;br /&gt;
    self:addClass(args.class)&lt;br /&gt;
    self.style = args.style&lt;br /&gt;
&lt;br /&gt;
    -- Set text style.&lt;br /&gt;
    self.textstyle = args.textstyle&lt;br /&gt;
&lt;br /&gt;
    -- Process data for collapsible text fields. At the moment these are only used in {{ambox}}.&lt;br /&gt;
    self.useCollapsibleTextFields = cfg.useCollapsibleTextFields &lt;br /&gt;
    if self.useCollapsibleTextFields then&lt;br /&gt;
        self.name = args.name&lt;br /&gt;
        local nameTitle = getTitleObject(self.name)&lt;br /&gt;
        self.isTemplatePage = nameTitle and self.title.prefixedText == ('Template:' .. nameTitle.text) and true or false&lt;br /&gt;
&lt;br /&gt;
        -- Get the self.issue value.&lt;br /&gt;
        if self.isSmall and args.smalltext then&lt;br /&gt;
            self.issue = args.smalltext&lt;br /&gt;
        else&lt;br /&gt;
            local sect&lt;br /&gt;
            if args.sect == '' then&lt;br /&gt;
                sect = 'This ' .. (cfg.sectionDefault or 'page')&lt;br /&gt;
            elseif type(args.sect) == 'string' then&lt;br /&gt;
                sect = 'This ' .. args.sect&lt;br /&gt;
            end&lt;br /&gt;
            local issue = args.issue&lt;br /&gt;
            issue = type(issue) == 'string' and issue or nil&lt;br /&gt;
            local text = args.text&lt;br /&gt;
            text = type(text) == 'string' and text or nil&lt;br /&gt;
            local issues = {}&lt;br /&gt;
            tinsert(issues, sect)&lt;br /&gt;
            tinsert(issues, issue)&lt;br /&gt;
            tinsert(issues, text)&lt;br /&gt;
            self.issue = tconcat(issues, ' ')&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        -- Get the self.talk value.&lt;br /&gt;
        local talk = args.talk&lt;br /&gt;
        if talk == '' and self.isTemplatePage then&lt;br /&gt;
            talk = '#'&lt;br /&gt;
        end&lt;br /&gt;
        if talk then&lt;br /&gt;
            -- See if the talk link exists and is for a talk or a content namespace.&lt;br /&gt;
            local talkTitle = getTitleObject(talk)&lt;br /&gt;
            if not talkTitle or not talkTitle.isTalkPage then&lt;br /&gt;
                -- If we couldn't process the talk page link, get the talk page of the current page.&lt;br /&gt;
                local success&lt;br /&gt;
                success, talkTitle = pcall(self.title.talkPageTitle, self.title)&lt;br /&gt;
                if not success then&lt;br /&gt;
                    talkTitle = nil&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
            if talkTitle and talkTitle.exists then&lt;br /&gt;
                local talkText = 'Relevant discussion may be found on'&lt;br /&gt;
                if talkTitle.isTalkPage then&lt;br /&gt;
                    talkText = format('%s [[%s|%s]].', talkText, talk, talkTitle.prefixedText)&lt;br /&gt;
                else&lt;br /&gt;
                    talkText = format('%s the [[%s#%s|talk page]].', talkText, talkTitle.prefixedText, talk)&lt;br /&gt;
                end&lt;br /&gt;
                self.talk = talkText&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        -- Get other values.&lt;br /&gt;
        self.fix = args.fix&lt;br /&gt;
        local date&lt;br /&gt;
        if args.date and args.date ~= '' then&lt;br /&gt;
            date = args.date&lt;br /&gt;
        elseif args.date == '' and self.isTemplatePage then&lt;br /&gt;
            date = lang:formatDate('F Y')&lt;br /&gt;
        end&lt;br /&gt;
        if date then&lt;br /&gt;
            self.date = format(&amp;quot; &amp;lt;small&amp;gt;''(%s)''&amp;lt;/small&amp;gt;&amp;quot;, date)&lt;br /&gt;
        end&lt;br /&gt;
        self.info = args.info&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Set the non-collapsible text field. At the moment this is used by all box types other than ambox,&lt;br /&gt;
    -- and also by ambox when small=yes.&lt;br /&gt;
    if self.isSmall then&lt;br /&gt;
        self.text = args.smalltext or args.text&lt;br /&gt;
    else&lt;br /&gt;
        self.text = args.text&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Set the below row.&lt;br /&gt;
    self.below = cfg.below and args.below&lt;br /&gt;
&lt;br /&gt;
    -- General image settings.&lt;br /&gt;
    self.imageCellDiv = not self.isSmall and cfg.imageCellDiv and true or false&lt;br /&gt;
    self.imageEmptyCell = cfg.imageEmptyCell&lt;br /&gt;
    if cfg.imageEmptyCellStyle then&lt;br /&gt;
        self.imageEmptyCellStyle = 'border:none;padding:0px;width:1px'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Left image settings.&lt;br /&gt;
    local imageLeft = self.isSmall and args.smallimage or args.image&lt;br /&gt;
    if cfg.imageCheckBlank and imageLeft ~= 'blank' and imageLeft ~= 'none'&lt;br /&gt;
        or not cfg.imageCheckBlank and imageLeft ~= 'none'&lt;br /&gt;
    then&lt;br /&gt;
        self.imageLeft = imageLeft&lt;br /&gt;
        if not imageLeft then&lt;br /&gt;
            local imageSize = self.isSmall and (cfg.imageSmallSize or '30x30px') or '40x40px'&lt;br /&gt;
            self.imageLeft = format('[[File:%s|%s|link=|alt=]]', self.typeImage or 'Imbox notice.png', imageSize)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Right image settings.&lt;br /&gt;
    local imageRight = self.isSmall and args.smallimageright or args.imageright&lt;br /&gt;
    if not (cfg.imageRightNone and imageRight == 'none') then&lt;br /&gt;
        self.imageRight = imageRight&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Add mainspace categories. At the moment these are only used in {{ambox}}.&lt;br /&gt;
    if cfg.allowMainspaceCategories then&lt;br /&gt;
        if args.cat then&lt;br /&gt;
            args.cat1 = args.cat&lt;br /&gt;
        end&lt;br /&gt;
        self.catNums = getArgNums(args, 'cat')&lt;br /&gt;
        if args.category then&lt;br /&gt;
            args.category1 = args.category&lt;br /&gt;
        end&lt;br /&gt;
        self.categoryNums = getArgNums(args, 'category')&lt;br /&gt;
        self.categoryParamNums = union(self.catNums, self.categoryNums)&lt;br /&gt;
        if args.all then&lt;br /&gt;
            args.all1 = args.all&lt;br /&gt;
        end&lt;br /&gt;
        -- The following is roughly equivalent to the old {{Ambox/category}}.&lt;br /&gt;
        local date = args.date&lt;br /&gt;
        date = type(date) == 'string' and date&lt;br /&gt;
        local preposition = 'from'&lt;br /&gt;
        for _, num in ipairs(self.categoryParamNums) do&lt;br /&gt;
            local mainCat = args['cat' .. tostring(num)] or args['category' .. tostring(num)]&lt;br /&gt;
            local allCat = args['all' .. tostring(num)]&lt;br /&gt;
            mainCat = type(mainCat) == 'string' and mainCat&lt;br /&gt;
            allCat = type(allCat) == 'string' and allCat&lt;br /&gt;
            if mainCat and date then&lt;br /&gt;
                local catTitle = format('%s %s %s', mainCat, preposition, date)&lt;br /&gt;
                self:addCat('main', catTitle)&lt;br /&gt;
                catTitle = getTitleObject('Category:' .. catTitle)&lt;br /&gt;
                if not catTitle or not catTitle.exists then&lt;br /&gt;
                    self:addCat('main', 'Articles with invalid date parameter in template')&lt;br /&gt;
                end&lt;br /&gt;
            elseif mainCat and not date then&lt;br /&gt;
                self:addCat('main', mainCat)&lt;br /&gt;
            end&lt;br /&gt;
            if allCat then&lt;br /&gt;
                self:addCat('main', allCat)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Add template-namespace categories.&lt;br /&gt;
    self.isTemplatePage = type(self.name) == 'string' and self.title.prefixedText == ('Template:' .. self.name)&lt;br /&gt;
    if cfg.templateCategory then&lt;br /&gt;
        if self.name then&lt;br /&gt;
            if self.isTemplatePage then&lt;br /&gt;
                self:addCat('template', cfg.templateCategory)&lt;br /&gt;
            end&lt;br /&gt;
        elseif not self.title.isSubpage then&lt;br /&gt;
            self:addCat('template', cfg.templateCategory)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- Add template error category.&lt;br /&gt;
    if cfg.templateErrorCategory then&lt;br /&gt;
        local templateErrorCategory = cfg.templateErrorCategory&lt;br /&gt;
        local templateCat, templateSort&lt;br /&gt;
        if not self.name and not self.title.isSubpage then&lt;br /&gt;
            templateCat = templateErrorCategory&lt;br /&gt;
        elseif type(self.name) == 'string' and self.title.prefixedText == ('Template:' .. self.name) then&lt;br /&gt;
            local paramsToCheck = cfg.templateErrorParamsToCheck or {}&lt;br /&gt;
            local count = 0&lt;br /&gt;
            for i, param in ipairs(paramsToCheck) do&lt;br /&gt;
                if not args[param] then&lt;br /&gt;
                    count = count + 1&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
            if count &amp;gt; 0 then&lt;br /&gt;
                templateCat = templateErrorCategory&lt;br /&gt;
                templateSort = tostring(count)&lt;br /&gt;
            end&lt;br /&gt;
            if self.categoryNums and #self.categoryNums &amp;gt; 0 then&lt;br /&gt;
                templateCat = templateErrorCategory&lt;br /&gt;
                templateSort = 'C'&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        self:addCat('template', templateCat, templateSort)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Categories for all namespaces.&lt;br /&gt;
    if self.invalidTypeError then&lt;br /&gt;
        local allSort = (nsid == 0 and 'Main:' or '') .. self.title.prefixedText&lt;br /&gt;
        self:addCat('all', 'Wikipedia message box parameter needs fixing', allSort)&lt;br /&gt;
    end&lt;br /&gt;
    if self.isSubstituted then&lt;br /&gt;
        self:addCat('all', 'Pages with incorrectly substituted templates')&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Convert category tables to strings and pass them through [[Module:Category handler]].&lt;br /&gt;
    self.categories = categoryHandler{&lt;br /&gt;
        main = tconcat(self.mainCats or {}),&lt;br /&gt;
        template = tconcat(self.templateCats or {}),&lt;br /&gt;
        all = tconcat(self.allCats or {}),&lt;br /&gt;
        nocat = args.nocat,&lt;br /&gt;
        demospace = self.demospace,&lt;br /&gt;
        page = self.pageTitle and self.pageTitle.prefixedText or nil&lt;br /&gt;
    }&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box:export()&lt;br /&gt;
    local root = htmlBuilder.create()&lt;br /&gt;
&lt;br /&gt;
    -- Add the subst check error.&lt;br /&gt;
    if self.isSubstituted and self.name then&lt;br /&gt;
        root&lt;br /&gt;
            .tag('b')&lt;br /&gt;
                .addClass('error')&lt;br /&gt;
                .wikitext(format(&lt;br /&gt;
                    'Template &amp;lt;code&amp;gt;%s[[Template:%s|%s]]%s&amp;lt;/code&amp;gt; has been incorrectly substituted.',&lt;br /&gt;
                    mw.text.nowiki('{{'), self.name, self.name, mw.text.nowiki('}}')&lt;br /&gt;
                ))&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Create the box table.&lt;br /&gt;
    local boxTable = root.tag('table')&lt;br /&gt;
    boxTable&lt;br /&gt;
        .attr('id', self.id)&lt;br /&gt;
    for i, class in ipairs(self.classes or {}) do&lt;br /&gt;
        boxTable&lt;br /&gt;
            .addClass(class)&lt;br /&gt;
    end&lt;br /&gt;
    boxTable&lt;br /&gt;
        .cssText(self.style)&lt;br /&gt;
        .attr('role', 'presentation')&lt;br /&gt;
&lt;br /&gt;
    -- Add the left-hand image.&lt;br /&gt;
    local row = boxTable.tag('tr')&lt;br /&gt;
    if self.imageLeft then&lt;br /&gt;
        local imageLeftCell = row.tag('td').addClass('mbox-image')&lt;br /&gt;
        if self.imageCellDiv then&lt;br /&gt;
            -- If we are using a div, redefine imageLeftCell so that the image is inside it.&lt;br /&gt;
            -- Divs use style=&amp;quot;width: 52px;&amp;quot;, which limits the image width to 52px. If any&lt;br /&gt;
            -- images in a div are wider than that, they may overlap with the text or cause&lt;br /&gt;
            -- other display problems.&lt;br /&gt;
            imageLeftCell = imageLeftCell.tag('div').css('width', '52px') &lt;br /&gt;
        end&lt;br /&gt;
        imageLeftCell&lt;br /&gt;
            .wikitext(self.imageLeft)&lt;br /&gt;
    elseif self.imageEmptyCell then&lt;br /&gt;
        -- Some message boxes define an empty cell if no image is specified, and some don't.&lt;br /&gt;
        -- The old template code in templates where empty cells are specified gives the following hint:&lt;br /&gt;
        -- &amp;quot;No image. Cell with some width or padding necessary for text cell to have 100% width.&amp;quot;&lt;br /&gt;
        row.tag('td')&lt;br /&gt;
            .addClass('mbox-empty-cell') &lt;br /&gt;
            .cssText(self.imageEmptyCellStyle)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Add the text.&lt;br /&gt;
    local textCell = row.tag('td').addClass('mbox-text')&lt;br /&gt;
    if self.useCollapsibleTextFields then&lt;br /&gt;
        -- The message box uses advanced text parameters that allow things to be collapsible. At the&lt;br /&gt;
        -- moment, only ambox uses this.&lt;br /&gt;
        textCell&lt;br /&gt;
            .cssText(self.textstyle)&lt;br /&gt;
        local textCellSpan = textCell.tag('span')&lt;br /&gt;
        textCellSpan&lt;br /&gt;
            .addClass('mbox-text-span')&lt;br /&gt;
            .wikitext(self.issue)&lt;br /&gt;
        if not self.isSmall then&lt;br /&gt;
            textCellSpan&lt;br /&gt;
                .tag('span')&lt;br /&gt;
                    .addClass('hide-when-compact')&lt;br /&gt;
                    .wikitext(self.talk and ' ' .. self.talk)&lt;br /&gt;
                    .wikitext(self.fix and ' ' .. self.fix)&lt;br /&gt;
        end&lt;br /&gt;
        textCellSpan&lt;br /&gt;
            .wikitext(self.date and ' ' .. self.date)&lt;br /&gt;
        if not self.isSmall then&lt;br /&gt;
            textCellSpan&lt;br /&gt;
                .tag('span')&lt;br /&gt;
                    .addClass('hide-when-compact')&lt;br /&gt;
                    .wikitext(self.info and ' ' .. self.info)&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        -- Default text formatting - anything goes.&lt;br /&gt;
        textCell&lt;br /&gt;
            .cssText(self.textstyle)&lt;br /&gt;
            .wikitext(self.text)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Add the right-hand image.&lt;br /&gt;
    if self.imageRight then&lt;br /&gt;
        local imageRightCell = row.tag('td').addClass('mbox-imageright')&lt;br /&gt;
        if self.imageCellDiv then&lt;br /&gt;
            imageRightCell = imageRightCell.tag('div').css('width', '52px') -- If we are using a div, redefine imageRightCell so that the image is inside it.&lt;br /&gt;
        end&lt;br /&gt;
        imageRightCell&lt;br /&gt;
            .wikitext(self.imageRight)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Add the below row.&lt;br /&gt;
    if self.below then&lt;br /&gt;
        boxTable.tag('tr')&lt;br /&gt;
            .tag('td')&lt;br /&gt;
                .attr('colspan', self.imageRight and '3' or '2')&lt;br /&gt;
                .addClass('mbox-text')&lt;br /&gt;
                .cssText(self.textstyle)&lt;br /&gt;
                .wikitext(self.below)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Add error message for invalid type parameters.&lt;br /&gt;
    if self.invalidTypeError then&lt;br /&gt;
        root&lt;br /&gt;
            .tag('div')&lt;br /&gt;
                .css('text-align', 'center')&lt;br /&gt;
                .wikitext(format('This message box is using an invalid &amp;quot;type=%s&amp;quot; parameter and needs fixing.', self.type or ''))&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Add categories.&lt;br /&gt;
    root&lt;br /&gt;
        .wikitext(self.categories)&lt;br /&gt;
&lt;br /&gt;
    return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function makeBox(boxType, args)&lt;br /&gt;
    box:setTitle(args)&lt;br /&gt;
    local cfg = box:getConfig(boxType)&lt;br /&gt;
    args = box:removeBlankArgs(cfg, args)&lt;br /&gt;
    box:setBoxParameters(cfg, args)&lt;br /&gt;
    return box:export()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function makeWrapper(boxType)&lt;br /&gt;
    return function (frame)&lt;br /&gt;
        -- If called via #invoke, use the args passed into the invoking&lt;br /&gt;
        -- template, or the args passed to #invoke if any exist. Otherwise&lt;br /&gt;
        -- assume args are being passed directly in from the debug console&lt;br /&gt;
        -- or from another Lua module.&lt;br /&gt;
        local origArgs&lt;br /&gt;
        if frame == mw.getCurrentFrame() then&lt;br /&gt;
            origArgs = frame:getParent().args&lt;br /&gt;
            for k, v in pairs(frame.args) do&lt;br /&gt;
                origArgs = frame.args&lt;br /&gt;
                break&lt;br /&gt;
            end&lt;br /&gt;
        else&lt;br /&gt;
            origArgs = frame&lt;br /&gt;
        end&lt;br /&gt;
        -- Trim whitespace.&lt;br /&gt;
        local args = {}&lt;br /&gt;
        for k, v in pairs(origArgs) do&lt;br /&gt;
            if type(v) == 'string' then&lt;br /&gt;
                v = trim(v)&lt;br /&gt;
            end&lt;br /&gt;
            args[k] = v&lt;br /&gt;
        end&lt;br /&gt;
        return makeBox(boxType, args)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local p = {&lt;br /&gt;
    box = box,&lt;br /&gt;
    makeBox = makeBox,&lt;br /&gt;
    mbox = makeWrapper('mbox')&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
for boxType in pairs(cfgTables) do&lt;br /&gt;
    p[boxType] = makeWrapper(boxType)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius on tour</name></author>	</entry>

	</feed>