<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://themidnight.wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3ATemplateBox</id>
	<title>Module:TemplateBox - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://themidnight.wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3ATemplateBox"/>
	<link rel="alternate" type="text/html" href="https://themidnight.wiki/index.php?title=Module:TemplateBox&amp;action=history"/>
	<updated>2026-04-03T21:08:46Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.41.1</generator>
	<entry>
		<id>https://themidnight.wiki/index.php?title=Module:TemplateBox&amp;diff=7738&amp;oldid=prev</id>
		<title>Timothy: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://themidnight.wiki/index.php?title=Module:TemplateBox&amp;diff=7738&amp;oldid=prev"/>
		<updated>2023-06-12T15:53:35Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 11:53, 12 June 2023&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Timothy</name></author>
	</entry>
	<entry>
		<id>https://themidnight.wiki/index.php?title=Module:TemplateBox&amp;diff=7737&amp;oldid=prev</id>
		<title>wikimedia&gt;WOSlinker: use require(&#039;strict&#039;) instead of require(&#039;Module:No globals&#039;)</title>
		<link rel="alternate" type="text/html" href="https://themidnight.wiki/index.php?title=Module:TemplateBox&amp;diff=7737&amp;oldid=prev"/>
		<updated>2022-10-30T13:19:31Z</updated>

		<summary type="html">&lt;p&gt;use require(&amp;#039;strict&amp;#039;) instead of require(&amp;#039;Module:No globals&amp;#039;)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;require(&amp;#039;strict&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
    @exports&lt;br /&gt;
        usagesample( frame )&lt;br /&gt;
        argcount( frame )&lt;br /&gt;
        args2table( args, onGetKey, forCustom )&lt;br /&gt;
        paramtable( frame )&lt;br /&gt;
        description( frame )&lt;br /&gt;
        templatedata( frame )&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Helper function, not exposed&lt;br /&gt;
local function tobool(st)&lt;br /&gt;
    if type( st ) == &amp;#039;string&amp;#039; then&lt;br /&gt;
        return st == &amp;#039;true&amp;#039;&lt;br /&gt;
    else&lt;br /&gt;
        return not not st&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- Required to determine in which languages the interface texts without langcode are&lt;br /&gt;
local contentLangcode = mw.language.getContentLanguage():getCode()&lt;br /&gt;
-- Forward declaration&lt;br /&gt;
local msg, langIsInit, userLang&lt;br /&gt;
local messagePrefix = &amp;quot;templatedata-doc-&amp;quot;&lt;br /&gt;
local i18n = {}&lt;br /&gt;
i18n[&amp;#039;params&amp;#039;] = &amp;quot;Template parameters&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-name&amp;#039;] = &amp;quot;Parameter&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-desc&amp;#039;] = &amp;quot;Description&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-type&amp;#039;] = &amp;quot;Type&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-default&amp;#039;] = &amp;quot;Default&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-status&amp;#039;] = &amp;quot;Status&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-status-optional&amp;#039;] = &amp;quot;optional&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-status-required&amp;#039;] = &amp;quot;required&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-status-suggested&amp;#039;] = &amp;quot;suggested&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-status-deprecated&amp;#039;] = &amp;quot;deprecated&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-default-empty&amp;#039;] = &amp;quot;empty&amp;quot;&lt;br /&gt;
&lt;br /&gt;
local function initLangModule(frame)&lt;br /&gt;
    if langIsInit then&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    userLang = frame:preprocess( &amp;#039;{{int:lang}}&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
    --! From [[:de:Modul:Expr]]; by [[:de:User:PerfektesChaos]]; &lt;br /&gt;
    --! Derivative work: Rillke&lt;br /&gt;
    msg = function( key )&lt;br /&gt;
        -- Retrieve localized message string in content language&lt;br /&gt;
        -- Precondition:&lt;br /&gt;
        --     key  -- string; message ID&lt;br /&gt;
        -- Postcondition:&lt;br /&gt;
        --     Return some message string&lt;br /&gt;
        -- Uses:&lt;br /&gt;
        --     &amp;gt;  messagePrefix&lt;br /&gt;
        --     &amp;gt;  i18n&lt;br /&gt;
        --     &amp;gt;  userLang&lt;br /&gt;
        --     mw.message.new()&lt;br /&gt;
        local m = mw.message.new( messagePrefix .. key )&lt;br /&gt;
        local r = false&lt;br /&gt;
        if m:isBlank() then&lt;br /&gt;
            r = i18n[ key ]&lt;br /&gt;
        else&lt;br /&gt;
            m:inLanguage( userLang )&lt;br /&gt;
            r = m:plain()&lt;br /&gt;
        end&lt;br /&gt;
        if not r then&lt;br /&gt;
            r = &amp;#039;(((&amp;#039;.. key .. &amp;#039;)))&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
        return r&lt;br /&gt;
    end -- msg()&lt;br /&gt;
    &lt;br /&gt;
    langIsInit = true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- A &amp;quot;hash&amp;quot; / table of everything TemplateData takes&lt;br /&gt;
-- to ease maintenance.&lt;br /&gt;
&lt;br /&gt;
-- The type is automatically determined if t is omitted.&lt;br /&gt;
-- If the type does not match or can&amp;#039;t be converted, an error will be thrown!&lt;br /&gt;
-- Available types (LUA-Types with exceptions): &lt;br /&gt;
--      InterfaceText, boolean, number, selection, table, string&lt;br /&gt;
-- selection*: - requires a selection-string of pipe-separated possibilities to be supplied&lt;br /&gt;
-- InterfaceText*: A free-form string (no wikitext) in the content-language of the wiki, or, &lt;br /&gt;
-- an object containing those strings keyed by language code.&lt;br /&gt;
local paraminfoTemplate = {&lt;br /&gt;
    description = {&lt;br /&gt;
        default = &amp;#039;&amp;#039;,&lt;br /&gt;
        t = &amp;#039;InterfaceText&amp;#039;,&lt;br /&gt;
        alias = &amp;#039;desc&amp;#039;&lt;br /&gt;
    },&lt;br /&gt;
    format = {&lt;br /&gt;
		default = &amp;#039;inline&amp;#039;,&lt;br /&gt;
		t = &amp;#039;selection&amp;#039;,&lt;br /&gt;
		selection = &amp;#039;inline|block&amp;#039;,&lt;br /&gt;
		alias = &amp;#039;print&amp;#039;,&lt;br /&gt;
		extract = function(pargs, number, paramVal)&lt;br /&gt;
			local m = { multi = &amp;#039;block&amp;#039;, one = &amp;#039;inline&amp;#039;, infobox = &amp;#039;block&amp;#039; }&lt;br /&gt;
            return m[paramVal] or &amp;#039;inline&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
local paraminfoTLParams = {&lt;br /&gt;
    label = {&lt;br /&gt;
        default = &amp;#039;&amp;#039;,&lt;br /&gt;
        t = &amp;#039;InterfaceText&amp;#039;&lt;br /&gt;
    },&lt;br /&gt;
    required = {&lt;br /&gt;
        default = false,&lt;br /&gt;
        extract = function(pargs, number, paramVal)&lt;br /&gt;
            local req = (pargs[number .. &amp;#039;stat&amp;#039;] == &amp;#039;required&amp;#039;)&lt;br /&gt;
            return tobool( paramVal or req )&lt;br /&gt;
        end&lt;br /&gt;
    },&lt;br /&gt;
    suggested = {&lt;br /&gt;
        default = false,&lt;br /&gt;
        extract = function(pargs, number, paramVal)&lt;br /&gt;
            local sugg = (pargs[number .. &amp;#039;stat&amp;#039;] == &amp;#039;suggested&amp;#039;)&lt;br /&gt;
            return tobool( paramVal or sugg )&lt;br /&gt;
        end&lt;br /&gt;
    },&lt;br /&gt;
    description = {&lt;br /&gt;
        default = &amp;#039;&amp;#039;,&lt;br /&gt;
        t = &amp;#039;InterfaceText&amp;#039;,&lt;br /&gt;
        alias = &amp;#039;d&amp;#039;&lt;br /&gt;
    },&lt;br /&gt;
    deprecated = {&lt;br /&gt;
        default = false,&lt;br /&gt;
        extract = function(pargs, number, paramVal)&lt;br /&gt;
            local depr = (pargs[number .. &amp;#039;stat&amp;#039;] == &amp;#039;deprecated&amp;#039;)&lt;br /&gt;
            return tobool( paramVal or depr )&lt;br /&gt;
        end&lt;br /&gt;
    },&lt;br /&gt;
    aliases = {&lt;br /&gt;
        default = &amp;#039;&amp;#039;,&lt;br /&gt;
        t = &amp;#039;table&amp;#039;,&lt;br /&gt;
        extract = function(pargs, number, paramVal)&lt;br /&gt;
            local key = number .. &amp;#039;aliases&amp;#039;&lt;br /&gt;
            local tdkey = key .. &amp;#039;-td&amp;#039;&lt;br /&gt;
            local aliases = pargs[tdkey] or pargs[key]&lt;br /&gt;
            if aliases and mw.text.trim( aliases ) ~= &amp;#039;&amp;#039; then&lt;br /&gt;
                local cleaned = {}&lt;br /&gt;
                for m in mw.text.gsplit( aliases, &amp;#039;/&amp;#039;, true ) do&lt;br /&gt;
                    cleaned[#cleaned+1] = mw.text.trim(m)&lt;br /&gt;
                end&lt;br /&gt;
                return cleaned&lt;br /&gt;
            else&lt;br /&gt;
                return nil&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    },&lt;br /&gt;
    default = {&lt;br /&gt;
        default = &amp;#039;&amp;#039;,&lt;br /&gt;
        t = &amp;#039;string&amp;#039;,&lt;br /&gt;
        alias = &amp;#039;def&amp;#039;&lt;br /&gt;
    },&lt;br /&gt;
    type = {&lt;br /&gt;
        default = &amp;#039;unknown&amp;#039;,&lt;br /&gt;
        t = &amp;#039;selection&amp;#039;,&lt;br /&gt;
        selection = &amp;#039;unknown|number|string|string/wiki-user-name|string/wiki-page-name|string/line|line|wiki-page-name|wiki-file-name|wiki-user-name|wiki-template-name|content|unbalanced-wikitext|date|url|boolean&amp;#039;&lt;br /&gt;
    },&lt;br /&gt;
    inherits = {&lt;br /&gt;
        default = nil,&lt;br /&gt;
        t = &amp;#039;string&amp;#039;&lt;br /&gt;
    },&lt;br /&gt;
    autovalue = {&lt;br /&gt;
        default = &amp;#039;&amp;#039;,&lt;br /&gt;
        t = &amp;#039;string&amp;#039;,&lt;br /&gt;
        alias = &amp;#039;av&amp;#039;,&lt;br /&gt;
    },&lt;br /&gt;
    suggestedvalues = {&lt;br /&gt;
        default = &amp;#039;&amp;#039;,&lt;br /&gt;
        t = &amp;#039;table&amp;#039;,&lt;br /&gt;
        alias = &amp;#039;sv&amp;#039;,&lt;br /&gt;
        extract = function(pargs, number, paramVal)&lt;br /&gt;
            if paramVal == nil then&lt;br /&gt;
                return nil&lt;br /&gt;
            end&lt;br /&gt;
            local cleaned = {}&lt;br /&gt;
            for m in mw.text.gsplit( paramVal, &amp;#039;/&amp;#039;, true ) do&lt;br /&gt;
                cleaned[#cleaned+1] = mw.text.trim(m)&lt;br /&gt;
            end&lt;br /&gt;
            return cleaned&lt;br /&gt;
        end,&lt;br /&gt;
    },&lt;br /&gt;
    -- sets will be treated differently because we can only have a plain structure in wikitext&lt;br /&gt;
}&lt;br /&gt;
local tableLayout = {&lt;br /&gt;
    {&lt;br /&gt;
        col = &amp;#039;param-name&amp;#039;,&lt;br /&gt;
        width = &amp;#039;15%&amp;#039;,&lt;br /&gt;
        extract = function(item, renderCell, monolingual)&lt;br /&gt;
            local alias, param = &amp;#039;&amp;#039;, item.key&lt;br /&gt;
            local aliasTT = &amp;#039;&amp;lt;span style=&amp;quot;font-family: monospace; color:#777; border:1px solid #6A6A6A&amp;quot;&amp;gt;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
            param = &amp;#039;&amp;lt;code&amp;gt;&amp;#039; .. param .. &amp;#039;&amp;lt;/code&amp;gt;&amp;#039;&lt;br /&gt;
            if item.aliases then&lt;br /&gt;
                alias = aliasTT .. table.concat(item.aliases, &amp;#039;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&amp;#039; .. aliasTT) .. &amp;#039;&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
                param = table.concat({param, &amp;#039;&amp;lt;br /&amp;gt;&amp;lt;div&amp;gt;&amp;#039;, alias, &amp;#039;&amp;lt;/div&amp;gt;&amp;#039;})&lt;br /&gt;
            end&lt;br /&gt;
            renderCell(param)&lt;br /&gt;
        end&lt;br /&gt;
    },  {&lt;br /&gt;
        col = &amp;#039;param-desc&amp;#039;,&lt;br /&gt;
        cols = 2,&lt;br /&gt;
        width = &amp;#039;65%&amp;#039;,&lt;br /&gt;
        extract = function(item, renderCell, monolingual)&lt;br /&gt;
            local label = item.label or &amp;#039;&amp;#039;&lt;br /&gt;
            label = monolingual(label)&lt;br /&gt;
            local labelLen = #label&lt;br /&gt;
            local colspan = 2 - labelLen&lt;br /&gt;
        &lt;br /&gt;
            if labelLen &amp;gt; 0 then&lt;br /&gt;
                renderCell(label)&lt;br /&gt;
            end&lt;br /&gt;
        &lt;br /&gt;
            renderCell(monolingual(item.description), colspan)&lt;br /&gt;
        end&lt;br /&gt;
    },  {&lt;br /&gt;
        col = &amp;#039;param-default&amp;#039;,&lt;br /&gt;
        width = &amp;#039;10%&amp;#039;,&lt;br /&gt;
        extract = function(item, renderCell, monolingual)&lt;br /&gt;
            local def = monolingual(item.default) or &amp;#039;&amp;#039;&lt;br /&gt;
            if #def == 0 then&lt;br /&gt;
                def = &amp;#039;&amp;lt;span class=&amp;quot;mw-templatedata-doc-muted&amp;quot; style=&amp;quot;color:#777; font-variant:small-caps&amp;quot;&amp;gt;&amp;#039; .. msg(&amp;#039;param-default-empty&amp;#039;) .. &amp;#039;&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
            renderCell(def)&lt;br /&gt;
        end&lt;br /&gt;
    },  {&lt;br /&gt;
        col = &amp;#039;param-status&amp;#039;,&lt;br /&gt;
        width = &amp;#039;10%&amp;#039;,&lt;br /&gt;
        extract = function(item, renderCell, monolingual)&lt;br /&gt;
            local stat = msg(&amp;#039;param-status-optional&amp;#039;)&lt;br /&gt;
            if item.required then&lt;br /&gt;
                stat = &amp;#039;&amp;lt;b&amp;gt;&amp;#039; .. msg(&amp;#039;param-status-required&amp;#039;) .. &amp;#039;&amp;lt;/b&amp;gt;&amp;#039;&lt;br /&gt;
            elseif item.deprecated then&lt;br /&gt;
                stat = msg(&amp;#039;param-status-deprecated&amp;#039;)&lt;br /&gt;
            elseif item.suggested then&lt;br /&gt;
                stat = msg(&amp;#039;param-status-suggested&amp;#039;)&lt;br /&gt;
            end&lt;br /&gt;
            renderCell(stat)&lt;br /&gt;
        end&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Initialize param info&lt;br /&gt;
-- Avoids having to add redundant information to the preceding tables&lt;br /&gt;
local function init( which )&lt;br /&gt;
    local setDefault = function(v)&lt;br /&gt;
        if v.t == nil and v.default ~= nil then&lt;br /&gt;
            v.t = type( v.default )&lt;br /&gt;
        end&lt;br /&gt;
        if v.selection then&lt;br /&gt;
        	local selection = mw.text.split(v.selection, &amp;#039;|&amp;#039;, true)&lt;br /&gt;
        	v.selection = {}&lt;br /&gt;
        	for _, sel in ipairs(selection) do&lt;br /&gt;
        		v.selection[sel] = true&lt;br /&gt;
        	end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    for a, v in pairs( which ) do&lt;br /&gt;
        setDefault(v)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
local function initParamTables()&lt;br /&gt;
    init( paraminfoTemplate )&lt;br /&gt;
    init( paraminfoTLParams )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
-------------------- USAGE PART ----------------------&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
function p.argcount( frame )&lt;br /&gt;
    local pargs = ( frame:getParent() or {} ).args or {}&lt;br /&gt;
    local ac = 0&lt;br /&gt;
    for i, arg in pairs( pargs ) do&lt;br /&gt;
        if (&amp;#039;number&amp;#039; == type(i)) then&lt;br /&gt;
            ac = ac + 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return ac&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.usagesample( frame )&lt;br /&gt;
    local pargs = ( frame:getParent() or {} ).args or {}&lt;br /&gt;
    local multiline = (pargs.lines == &amp;#039;multi&amp;#039; or pargs.print == &amp;#039;multi&amp;#039; or pargs.print == &amp;#039;infobox&amp;#039;)&lt;br /&gt;
    local align = pargs.print == &amp;#039;infobox&amp;#039;&lt;br /&gt;
    if not pargs.lines and not pargs.print and pargs.type == &amp;#039;infobox&amp;#039; then&lt;br /&gt;
        multiline = true&lt;br /&gt;
        align = true&lt;br /&gt;
    end&lt;br /&gt;
    local sepStart = &amp;#039; |&amp;#039;&lt;br /&gt;
    local sepEnd = multiline  and &amp;#039;\n&amp;#039; or &amp;#039;&amp;#039;&lt;br /&gt;
    local sep = sepEnd&lt;br /&gt;
    local subst = #(pargs.mustbesubst or &amp;#039;&amp;#039;) &amp;gt; 0 and &amp;#039;subst:&amp;#039; or &amp;#039;&amp;#039;&lt;br /&gt;
    local beforeEqual = multiline  and &amp;#039; &amp;#039; or &amp;#039;&amp;#039;&lt;br /&gt;
    local equal = beforeEqual .. &amp;#039;= &amp;#039;&lt;br /&gt;
    local templateTitle = pargs.name or &amp;#039;&amp;#039;&lt;br /&gt;
    local args, argName, result = {}&lt;br /&gt;
    local maxArgLen, eachArg = 0&lt;br /&gt;
    sep = sep .. sepStart&lt;br /&gt;
    &lt;br /&gt;
    local sparseIpairs = require(&amp;#039;Module:TableTools&amp;#039;).sparseIpairs&lt;br /&gt;
    local comapareLegacyVal = function(val)&lt;br /&gt;
        return val == &amp;#039;optional-&amp;#039; or val == &amp;#039;deprecated&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
    local shouldShow = function(i)&lt;br /&gt;
        if comapareLegacyVal(pargs[i .. &amp;#039;stat&amp;#039;]) or&lt;br /&gt;
            comapareLegacyVal(pargs[i .. &amp;#039;stat-td&amp;#039;]) or&lt;br /&gt;
            pargs[i .. &amp;#039;deprecated&amp;#039;] == true then &lt;br /&gt;
                return false&lt;br /&gt;
            end&lt;br /&gt;
        return true&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    eachArg = function(cb)&lt;br /&gt;
        for i, arg in sparseIpairs( pargs ) do&lt;br /&gt;
            if (&amp;#039;number&amp;#039; == type(i)) then&lt;br /&gt;
                argName = mw.text.trim( arg or &amp;#039;&amp;#039; )&lt;br /&gt;
                if #argName == 0 then&lt;br /&gt;
                    argName = tostring(i)&lt;br /&gt;
                end&lt;br /&gt;
                &lt;br /&gt;
                if shouldShow(i) then&lt;br /&gt;
                    cb(argName)&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    if align then&lt;br /&gt;
        eachArg(function( arg )&lt;br /&gt;
            local argL = #arg&lt;br /&gt;
            maxArgLen = argL &amp;gt; maxArgLen and argL or maxArgLen&lt;br /&gt;
        end)&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    eachArg(function( arg )&lt;br /&gt;
        local space = &amp;#039;&amp;#039;&lt;br /&gt;
        if align then&lt;br /&gt;
            space = (&amp;#039;&amp;amp;nbsp;&amp;#039;):rep(maxArgLen - #arg)&lt;br /&gt;
        end&lt;br /&gt;
        table.insert( args, argName .. space .. equal )&lt;br /&gt;
    end)&lt;br /&gt;
    &lt;br /&gt;
    if #args == 0 then&lt;br /&gt;
        sep = &amp;#039;&amp;#039;&lt;br /&gt;
        sepEnd = &amp;#039;&amp;#039;&lt;br /&gt;
        sepStart = &amp;#039;&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
    if #templateTitle == 0 then&lt;br /&gt;
        templateTitle = mw.title.getCurrentTitle().text&lt;br /&gt;
    end&lt;br /&gt;
    result = table.concat( args, sep )&lt;br /&gt;
    result = table.concat({ mw.text.nowiki(&amp;#039;{{&amp;#039;), subst, templateTitle, sep, result, sepEnd, &amp;#039;}}&amp;#039; })&lt;br /&gt;
    if multiline then&lt;br /&gt;
        -- Preserve whitespace in front of new lines&lt;br /&gt;
        result = frame:callParserFunction{ name = &amp;#039;#tag&amp;#039;, args = { &amp;#039;poem&amp;#039;, result } }&lt;br /&gt;
    end&lt;br /&gt;
    return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
------------------- GENERAL PART ---------------------&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
function p.args2table(args, onGetKey, consumer)&lt;br /&gt;
    initParamTables()&lt;br /&gt;
    &lt;br /&gt;
    local sets, asParamArray, laxtype, processParams, processDesc, unstrip&lt;br /&gt;
    if &amp;#039;paramtable&amp;#039; == consumer then&lt;br /&gt;
        asParamArray = true&lt;br /&gt;
        processParams = true&lt;br /&gt;
        laxtype = true&lt;br /&gt;
    elseif &amp;#039;templatedata&amp;#039; == consumer then&lt;br /&gt;
        sets = true&lt;br /&gt;
        processParams = true&lt;br /&gt;
        processDesc = true&lt;br /&gt;
        unstrip = true&lt;br /&gt;
    elseif &amp;#039;description&amp;#039; == consumer then&lt;br /&gt;
        processDesc = true&lt;br /&gt;
        laxtype = true&lt;br /&gt;
    end&lt;br /&gt;
    -- All kind of strange stuff with the arguments is done, so play safe and make a copy&lt;br /&gt;
    local pargs = mw.clone( args )&lt;br /&gt;
    -- Array-like table containing all parameter-numbers that were passed&lt;br /&gt;
    local templateArgs = {}&lt;br /&gt;
    -- Arguments that are localized (i.e. the user passed  1desc-en=English description of parameter one)&lt;br /&gt;
    local i18nTemplateArgs = {}&lt;br /&gt;
    -- Ensure that tables end up as array/object (esp. when they are empty)&lt;br /&gt;
    local tdata = {description=&amp;quot;&amp;quot;, params={}, sets={}}&lt;br /&gt;
    local isObject = { __tostring = function() return &amp;quot;JSON object&amp;quot; end }    isObject.__index = isObject&lt;br /&gt;
    local isArray  = { __tostring = function() return &amp;quot;JSON array&amp;quot;  end }    isArray.__index  = isArray&lt;br /&gt;
    setmetatable(tdata.params, isObject)&lt;br /&gt;
    setmetatable(tdata.sets, isArray)&lt;br /&gt;
    onGetKey = onGetKey or function( prefix, alias, param )&lt;br /&gt;
        local key, key2, tdkey, tdkey2&lt;br /&gt;
        key = prefix .. (alias or param)&lt;br /&gt;
        key2 = prefix .. param&lt;br /&gt;
        tdkey = key .. &amp;#039;-td&amp;#039;&lt;br /&gt;
        tdkey2 = key2 .. &amp;#039;-td&amp;#039;&lt;br /&gt;
        return tdkey, tdkey2, key, key2&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local extractData = function( pi, number )&lt;br /&gt;
        local prefix = number or &amp;#039;&amp;#039;&lt;br /&gt;
        local ppv, paramVal&lt;br /&gt;
        local key1, key2, key3, key4&lt;br /&gt;
        local paramKey, paramTable, processKey&lt;br /&gt;
        if number then&lt;br /&gt;
            paramKey = mw.text.trim( pargs[number] )&lt;br /&gt;
            if &amp;#039;&amp;#039; == paramKey then&lt;br /&gt;
                paramKey = tostring( number )&lt;br /&gt;
            end&lt;br /&gt;
            &lt;br /&gt;
            paramTable = {}&lt;br /&gt;
            if asParamArray then&lt;br /&gt;
                paramTable.key = paramKey&lt;br /&gt;
                table.insert(tdata.params, paramTable)&lt;br /&gt;
            else&lt;br /&gt;
                tdata.params[paramKey] = paramTable&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        for p, info in pairs( pi ) do&lt;br /&gt;
            key1, key2, key3, key4 = onGetKey(prefix, info.alias, p)&lt;br /&gt;
            paramVal = nil&lt;br /&gt;
            &lt;br /&gt;
            processKey = function(key)&lt;br /&gt;
                if paramVal ~= nil then return end&lt;br /&gt;
                local plain, multilingual = pargs[key], i18nTemplateArgs[key]&lt;br /&gt;
                paramVal = multilingual or plain&lt;br /&gt;
            end&lt;br /&gt;
            processKey( key1 )&lt;br /&gt;
            processKey( key2 )&lt;br /&gt;
            processKey( key3 )&lt;br /&gt;
            processKey( key4 )&lt;br /&gt;
            &lt;br /&gt;
            -- Ensure presence of entry in content language&lt;br /&gt;
            ppv = pargs[key1] or pargs[key2] or pargs[key3] or pargs[key4] or info.default&lt;br /&gt;
            if &amp;#039;table&amp;#039; == type( paramVal ) then&lt;br /&gt;
                if (nil == paramVal[contentLangcode]) then&lt;br /&gt;
                    paramVal[contentLangcode] = ppv&lt;br /&gt;
                end&lt;br /&gt;
            else&lt;br /&gt;
                paramVal = ppv&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            if &amp;#039;function&amp;#039; == type( info.extract ) then&lt;br /&gt;
                if &amp;#039;string&amp;#039; == type( paramVal ) then&lt;br /&gt;
                    paramVal = mw.text.trim( paramVal )&lt;br /&gt;
                    if &amp;#039;&amp;#039; == paramVal then&lt;br /&gt;
                        paramVal = nil&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
                paramVal = info.extract( pargs, number, paramVal )&lt;br /&gt;
            end&lt;br /&gt;
            &lt;br /&gt;
            local insertValue = function()&lt;br /&gt;
                if number then&lt;br /&gt;
                    paramTable[p] = paramVal&lt;br /&gt;
                else&lt;br /&gt;
                    tdata[p] = paramVal&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
            &lt;br /&gt;
            if info.selection then&lt;br /&gt;
                if info.selection[paramVal] then&lt;br /&gt;
                    insertValue()&lt;br /&gt;
                end&lt;br /&gt;
            elseif &amp;#039;InterfaceText&amp;#039; == info.t then&lt;br /&gt;
                if ({ table=1, string=1 })[type( paramVal )] then&lt;br /&gt;
                    insertValue()&lt;br /&gt;
                end&lt;br /&gt;
            else&lt;br /&gt;
                local paramType = type( paramVal )&lt;br /&gt;
                if &amp;#039;string&amp;#039; == info.t and &amp;#039;string&amp;#039; == paramType then&lt;br /&gt;
                    paramVal = mw.text.trim( paramVal )&lt;br /&gt;
                    if &amp;#039;&amp;#039; ~= paramVal then&lt;br /&gt;
                        insertValue()&lt;br /&gt;
                    end&lt;br /&gt;
                elseif &amp;#039;boolean&amp;#039; == info.t then&lt;br /&gt;
                    paramVal = tobool(paramVal)&lt;br /&gt;
                    insertValue()&lt;br /&gt;
                elseif &amp;#039;number&amp;#039; == info.t then&lt;br /&gt;
                    paramVal = tonumber(paramVal)&lt;br /&gt;
                    insertValue()&lt;br /&gt;
                elseif paramType == info.t then&lt;br /&gt;
                    insertValue()&lt;br /&gt;
                elseif paramType == &amp;#039;nil&amp;#039; then&lt;br /&gt;
                    -- Do nothing&lt;br /&gt;
                elseif not laxtype and &amp;#039;string&amp;#039; == info.t and &amp;#039;table&amp;#039; == paramType then&lt;br /&gt;
                    -- Convert multilingual object into content language string&lt;br /&gt;
                    paramVal = paramVal[contentLangcode]&lt;br /&gt;
                    insertValue()&lt;br /&gt;
                else&lt;br /&gt;
                    if laxtype then&lt;br /&gt;
                        insertValue()&lt;br /&gt;
                    else&lt;br /&gt;
                        error( p .. &amp;#039;: Is of type &amp;#039; ..  paramType .. &amp;#039; but should be of type &amp;#039; .. (info.t or &amp;#039;unknown&amp;#039;), 1 )&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        -- Now, treat sets&lt;br /&gt;
        if sets then&lt;br /&gt;
            key1 = prefix .. &amp;#039;set-td&amp;#039;&lt;br /&gt;
            key2 = prefix .. &amp;#039;set&amp;#039;&lt;br /&gt;
            paramVal = pargs[key1] or pargs[key2]&lt;br /&gt;
            if paramVal then&lt;br /&gt;
                local found = false&lt;br /&gt;
                for i, s in ipairs( tdata.sets ) do&lt;br /&gt;
                    if s.label == paramVal then&lt;br /&gt;
                        table.insert( s.params, p )&lt;br /&gt;
                        found = true&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
                if not found then&lt;br /&gt;
                    table.insert( tdata.sets, {&lt;br /&gt;
                        label = paramVal, &lt;br /&gt;
                        params = { p }&lt;br /&gt;
                    } )&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- First, analyse the structure of the provided arguments&lt;br /&gt;
    for a, v in pairs( pargs ) do&lt;br /&gt;
        if unstrip then&lt;br /&gt;
            v = mw.text.unstrip( v )&lt;br /&gt;
            pargs[a] = v&lt;br /&gt;
        end&lt;br /&gt;
        if type( a ) == &amp;#039;number&amp;#039; then&lt;br /&gt;
            table.insert( templateArgs, a )&lt;br /&gt;
        else&lt;br /&gt;
            local argSplit = mw.text.split( a, &amp;#039;-&amp;#039;, true )&lt;br /&gt;
            local argUnitl = {}&lt;br /&gt;
            local argAfter = {}&lt;br /&gt;
            local isTDArg = false&lt;br /&gt;
            local containsTD = a:find( &amp;#039;-td&amp;#039;, 1, true )&lt;br /&gt;
            for i, part in ipairs( argSplit ) do&lt;br /&gt;
                if isTDArg or (containsTD == nil and i &amp;gt; 1) then&lt;br /&gt;
                    -- This is likely a language version&lt;br /&gt;
                    table.insert( argAfter, part )&lt;br /&gt;
                else&lt;br /&gt;
                    table.insert( argUnitl, part )&lt;br /&gt;
                end&lt;br /&gt;
                if part == &amp;#039;td&amp;#039; then&lt;br /&gt;
                    isTDArg = true&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
            if #argAfter &amp;gt; 0 then&lt;br /&gt;
                argUnitl = table.concat( argUnitl, &amp;#039;-&amp;#039; )&lt;br /&gt;
                argAfter = table.concat( argAfter, &amp;#039;-&amp;#039; )&lt;br /&gt;
                i18nTemplateArgs[argUnitl] = i18nTemplateArgs[argUnitl] or {}&lt;br /&gt;
                i18nTemplateArgs[argUnitl][argAfter] = v&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    -- Then, start building the actual template&lt;br /&gt;
    if processDesc then&lt;br /&gt;
        extractData( paraminfoTemplate )&lt;br /&gt;
    end&lt;br /&gt;
    if processParams then&lt;br /&gt;
        -- Ensure that `templateArgs` contains indicies in ascending order&lt;br /&gt;
        table.sort( templateArgs )&lt;br /&gt;
        for i, number in pairs( templateArgs ) do&lt;br /&gt;
            extractData( paraminfoTLParams, number )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return tdata, #templateArgs&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
------------ CUSTOM PARAMETER TABLE PART -------------&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- A custom key-pref-function&lt;br /&gt;
local customOnGetKey = function( prefix, alias, param )&lt;br /&gt;
    local key, key2, tdkey, tdkey2&lt;br /&gt;
    key = prefix .. (alias or param)&lt;br /&gt;
    key2 = prefix .. param&lt;br /&gt;
    tdkey = key .. &amp;#039;-td&amp;#039;&lt;br /&gt;
    tdkey2 = key2 .. &amp;#039;-td&amp;#039;&lt;br /&gt;
    return key2, key, tdkey2, tdkey&lt;br /&gt;
end&lt;br /&gt;
local toUserLanguage = function(input)&lt;br /&gt;
    if type(input) == &amp;#039;table&amp;#039; then&lt;br /&gt;
        input = require( &amp;#039;Module:LangSwitch&amp;#039; )._langSwitch( input, userLang ) or &amp;#039;&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
    return input&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.description(frame)&lt;br /&gt;
    local pargs = ( frame:getParent() or {} ).args or {}&lt;br /&gt;
&lt;br /&gt;
    -- Initialize the language-related stuff&lt;br /&gt;
    initLangModule(frame)&lt;br /&gt;
&lt;br /&gt;
    local tdata, paramLen&lt;br /&gt;
    tdata, paramLen = p.args2table(pargs, customOnGetKey, &amp;#039;description&amp;#039;)&lt;br /&gt;
    return toUserLanguage(tdata.description)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function p.paramtable(frame)&lt;br /&gt;
    local pargs = ( frame:getParent() or {} ).args or {}&lt;br /&gt;
    local tdata, paramLen&lt;br /&gt;
    &lt;br /&gt;
    if &amp;#039;only&amp;#039; == pargs.useTemplateData then&lt;br /&gt;
        return &amp;#039;param table - output suppressed&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- Initialize the language-related stuff&lt;br /&gt;
    initLangModule(frame)&lt;br /&gt;
&lt;br /&gt;
    tdata, paramLen = p.args2table(pargs, customOnGetKey, &amp;#039;paramtable&amp;#039;)&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    if 0 == paramLen then&lt;br /&gt;
        return &amp;#039;&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local row, rows = &amp;#039;&amp;#039;, {}&lt;br /&gt;
    local renderCell = function(wikitext, colspan)&lt;br /&gt;
        local colspan, oTd = colspan or 1, &amp;#039;&amp;lt;td&amp;gt;&amp;#039;&lt;br /&gt;
        if colspan &amp;gt; 1 then&lt;br /&gt;
            oTd = &amp;#039;&amp;lt;td colspan=&amp;quot;&amp;#039; .. colspan .. &amp;#039;&amp;quot;&amp;gt;&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
        row = table.concat({ row, oTd, wikitext, &amp;#039;&amp;lt;/td&amp;gt;&amp;#039; })&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- Create the header&lt;br /&gt;
    for i, field in ipairs( tableLayout ) do&lt;br /&gt;
        local style = &amp;#039; style=&amp;quot;width:&amp;#039; .. field.width .. &amp;#039;&amp;quot;&amp;#039;&lt;br /&gt;
        local colspan = &amp;#039;&amp;#039;&lt;br /&gt;
        if field.cols then&lt;br /&gt;
            colspan = &amp;#039; colspan=&amp;quot;&amp;#039; .. field.cols .. &amp;#039;&amp;quot;&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
        local th = &amp;#039;&amp;lt;th&amp;#039; .. style .. colspan .. &amp;#039;&amp;gt;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
        row = row .. th .. msg(field.col) .. &amp;#039;&amp;lt;/th&amp;gt;&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
    table.insert(rows, row)&lt;br /&gt;
    &lt;br /&gt;
    -- Now transform the Lua-table into an HTML-table&lt;br /&gt;
    for i, item in ipairs( tdata.params ) do&lt;br /&gt;
        row = &amp;#039;&amp;#039;&lt;br /&gt;
        for i2, field in ipairs( tableLayout ) do&lt;br /&gt;
            field.extract(item, renderCell, toUserLanguage)&lt;br /&gt;
        end&lt;br /&gt;
        table.insert(rows, row)&lt;br /&gt;
    end&lt;br /&gt;
    return &amp;#039;&amp;lt;table class=&amp;quot;wikitable templatebox-table&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;#039; .. table.concat(rows, &amp;#039;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;#039;) .. &amp;#039;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
----------------- TEMPLATEDATA PART ------------------&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- A real parser/transformer would look differently but it would likely be much more complex&lt;br /&gt;
-- The TemplateData-portion for [[Template:TemplateBox]]&lt;br /&gt;
function p.templatedata(frame)&lt;br /&gt;
    local tdata&lt;br /&gt;
    local args = frame.args or {}&lt;br /&gt;
    local formatting = args.formatting&lt;br /&gt;
    local pargs = ( frame:getParent() or {} ).args or {}&lt;br /&gt;
    local useTemplateData = pargs.useTemplateData&lt;br /&gt;
&lt;br /&gt;
    if  (formatting == &amp;#039;pretty&amp;#039; and useTemplateData ~= &amp;#039;export&amp;#039;) or&lt;br /&gt;
        (not useTemplateData) or&lt;br /&gt;
        (useTemplateData == &amp;#039;export&amp;#039; and formatting ~= &amp;#039;pretty&amp;#039;) then&lt;br /&gt;
            local warning = &amp;quot;Warning: Module:TemplateBox - templatedata invoked but not requested by user (setting useTemplateData=1).&amp;quot;&lt;br /&gt;
            mw.log(warning)&lt;br /&gt;
            tdata = &amp;#039;{&amp;quot;description&amp;quot;:&amp;quot;&amp;#039; .. warning .. &amp;#039;&amp;quot;,&amp;quot;params&amp;quot;:{},&amp;quot;sets&amp;quot;:[]}&amp;#039;&lt;br /&gt;
            return tdata&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- Load the JSON-Module which will convert LUA tables into valid JSON&lt;br /&gt;
    local JSON = require(&amp;#039;Module:JSON&amp;#039;)&lt;br /&gt;
    JSON.strictTypes = true&lt;br /&gt;
    -- Obtain the object containing info&lt;br /&gt;
    tdata = p.args2table(pargs, nil, &amp;#039;templatedata&amp;#039;)&lt;br /&gt;
    -- And finally return the result&lt;br /&gt;
    if formatting == &amp;#039;pretty&amp;#039; then&lt;br /&gt;
        return JSON:encode_pretty(tdata)&lt;br /&gt;
    else&lt;br /&gt;
        return JSON:encode(tdata)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>wikimedia&gt;WOSlinker</name></author>
	</entry>
</feed>