Feed The Beast Wiki

Follow the Feed The Beast Wiki on Discord or Mastodon!

READ MORE

Feed The Beast Wiki
m (Debug trace)
m (Protected "Module:Navbox" ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)))
 
(42 intermediate revisions by 4 users not shown)
Line 28: Line 28:
 
Like list{} except it formats as a straight run of text rather than hlist. Can only contain
 
Like list{} except it formats as a straight run of text rather than hlist. Can only contain
 
string. ni{} or l{}
 
string. ni{} or l{}
  +
 
ni{}
 
ni{}
 
 
Invokes {{NI}} (or a facsimile, anyway)
 
Invokes {{NI}} (or a facsimile, anyway)
  +
  +
nid{}
  +
Invokes {{NID}} (or a facsimile, anyway)
 
 
 
l{}
 
l{}
Line 53: Line 56:
 
[1] = Name of the navbox definition to use
 
[1] = Name of the navbox definition to use
 
name = template name for generating the v.d.e links
 
name = template name for generating the v.d.e links
collapse = null or "navbox" to hide the navbox
 
"groups" to collapse just the groups
 
"open" to leave it entirely open.
 
opengroups = space-delimited string of groups to open. Give hthe group a "name" argument
 
to refer to it here.
 
 
}
 
}
 
]]
 
]]
  +
  +
local ipairs, pairs, rawget, type = ipairs, pairs, rawget, type
   
 
local util = require("Module:Utility_functions")
 
local util = require("Module:Utility_functions")
Line 67: Line 67:
 
addDataToOutput = function(self, context, output, options)
 
addDataToOutput = function(self, context, output, options)
 
local oldmod = context.mod
 
local oldmod = context.mod
context.mod = self.data.mod or oldmod
+
context.mod = self.data.mod or oldmod or "UNDEFINED"
  +
local oldmodname = context.modname
  +
context.modname = self.data.modname or oldmodname or "Undefined"
 
for i, item in ipairs(self.data) do
 
for i, item in ipairs(self.data) do
 
output((options.surround or {''})[1])
 
output((options.surround or {''})[1])
Line 101: Line 103:
 
expand = function(self, context, output)
 
expand = function(self, context, output)
 
output('<table class="navbox" cellspacing="0"><tr><td style="padding: 2px;">')
 
output('<table class="navbox" cellspacing="0"><tr><td style="padding: 2px;">')
output('<table class="nowraplinks collapsible ')
+
output('<table class="nowraplinks')
 
output(' mw-collapsible ')
if (not context.collapse) or (context.collapse == "navbox") then
+
if context.state == "plain" or context.state == "off" then
output('collapsed')
 
else
+
output('mw-collapsed')
output('uncollapsed')
 
 
end
 
end
output('" cellspacing="0" style="width:100%; background: transparent; color: inherit;">')
+
output('" cellspacing="0" style="width:100%; background: transparent; color: inherit;"')
  +
output(' data-expandtext="show" data-collapsetext="hide">')
 
output('<tr><th colspan="2" class="navbox-title"><span style="float:left;width:6em;text-align:left;">')
 
output('<tr><th colspan="2" class="navbox-title"><span style="float:left;width:6em;text-align:left;">')
 
output(mw.getCurrentFrame():expandTemplate{title="Navbar", args={mini="1", context.name}})
 
output(mw.getCurrentFrame():expandTemplate{title="Navbar", args={mini="1", context.name}})
Line 130: Line 132:
 
output('<tr><td colspan="2" class="navbox-list" style="width:100%; padding:0px;">')
 
output('<tr><td colspan="2" class="navbox-list" style="width:100%; padding:0px;">')
 
output('<div style="padding:0em 0.25em"> </div>')
 
output('<div style="padding:0em 0.25em"> </div>')
output('<table class="nowraplinks collapsible ')
+
output('<table class="nowraplinks mw-collapsible')
if (context.collapse == "groups") and (not context.opengroups[self.data.name]) then
 
output('collapsed')
 
else
 
output('uncollapsed')
 
end
 
 
-- These two semicolons stops something from wrapping tables in gratuitous divs
 
-- These two semicolons stops something from wrapping tables in gratuitous divs
output(' navbox-subgroup" cellspacing="0" style="width:100%;;">')
+
output(' navbox-subgroup" cellspacing="0" style="width:100%;"')
  +
output(' data-expandtext="show" data-collapsetext="hide">')
 
output('<tr><th class="navbox-title" colspan="2">')
 
output('<tr><th class="navbox-title" colspan="2">')
 
output('<span style="float:left;width:6em;">&nbsp;</span><span style="font-size: 100%;">')
 
output('<span style="float:left;width:6em;">&nbsp;</span><span style="font-size: 100%;">')
Line 166: Line 164:
 
return
 
return
 
end
 
end
  +
 
local hasChildLists = (type(self.data[1]) == "table") and ((self.data[1].elementType == "list") or (self.data[1].elementType == "line"))
 
 
 
output('<tr>')
 
output('<tr>')
Line 174: Line 174:
 
output('<td style="text-align:left;border-left-width:2px;border-left-style:solid;width:100%;padding:0px;"')
 
output('<td style="text-align:left;border-left-width:2px;border-left-style:solid;width:100%;padding:0px;"')
 
else
 
else
output('<td rowspan="2" style="text-align:left;border-left-width:2px;border-left-style:solid;width:100%;padding:0px;"')
+
output('<td colspan="2" style="')
  +
if hasChildLists then
 
output('text-align:left;')
 
end
  +
output('border-left-width:2px;border-left-style:solid;width:100%;padding:0px;"')
 
end
 
end
 
 
Line 183: Line 187:
 
end
 
end
 
 
local hasChildLists = (type(self.data[1]) == "table") and ((self.data[1].elementType == "list") or (self.data[1].elementType == "line"))
 
 
 
 
if hasChildLists then
 
if hasChildLists then
Line 192: Line 195:
 
context.odd = not context.odd
 
context.odd = not context.odd
 
output('<ul class="hlist" style="padding:0em 0.25em; margin: 0;">')
 
output('<ul class="hlist" style="padding:0em 0.25em; margin: 0;">')
self:addDataToOutput(context, output, {surround = {'<li>','</li>'}})
+
self:addDataToOutput(context, output, {surround = {' <li class="nowrap"> ',' </li> '}})
 
output('</ul>')
 
output('</ul>')
 
end
 
end
Line 208: Line 211:
 
output('<td>')
 
output('<td>')
 
else
 
else
output('<td rowspan="2">')
+
output('<td colspan="2">')
 
end
 
end
 
 
Line 224: Line 227:
 
else
 
else
 
local iconargs = {
 
local iconargs = {
  +
"",
 
item = (self.data.gicon or self.data[1]),
 
item = (self.data.gicon or self.data[1]),
 
size=16,
 
size=16,
mod=(self.data.mod or context.mod or "undefined")
+
mod=(self.data.mod or context.mod)
 
}
 
}
 
output(mw.getCurrentFrame():callParserFunction("#icon", iconargs))
 
output(mw.getCurrentFrame():callParserFunction("#icon", iconargs))
 
end
 
end
output(" ")
+
output("&nbsp;")
local linkargs = { self.data[2] or self.data[1], (self.data[3] or self.data[2]) or self.data[1] }
+
local linkargs = { self.data[2] or self.data[1], (self.data[3] or self.data[2]) or mw.getCurrentFrame():callParserFunction("#iconloc", {self.data[1], self.data.mod or context.mod, "name", mw.title.getCurrentTitle().subpageText:lower()})}
  +
output(language.link(linkargs))
 
end
  +
}
  +
  +
-- Invocation of {{NID}}, or at least the equivalent thereof.
  +
element.nid = {
  +
expand = function(self, context, output)
 
if self.data.icon then
  +
output("[[File:" .. self.data.icon .. "|16px|link=]]")
 
else
 
local iconargs = {
  +
"",
 
item = (self.data.gicon or self.data[1]),
 
size = 16,
  +
mod = (self.data.mod or context.mod)
  +
}
  +
output(mw.getCurrentFrame():callParserFunction("#icon", iconargs))
 
end
 
output("&nbsp;")
  +
local linkargs = { self.data[1] .. " (" .. context.modname .. ")", (self.data[2]) or mw.getCurrentFrame():callParserFunction("#iconloc", {self.data[1], self.data.mod or context.mod, "name", mw.title.getCurrentTitle().subpageText:lower()})}
 
output(language.link(linkargs))
 
output(language.link(linkargs))
 
end
 
end
Line 275: Line 299:
 
setmetatable(newthing, element[name])
 
setmetatable(newthing, element[name])
   
 
for k, v in pairs(args) do
local named = {}
 
local positional = {}
 
for k,v in pairs(args) do
 
 
if type(k) == "number" then
 
if type(k) == "number" then
positional[k] = v
+
if type(v) == "function" then
 
for j, w in ipairs(invokeInDefinition(v)) do
else
 
named[k] = v
+
table.insert(newthing.data, w)
end
+
end
end
+
else
 
table.insert(newthing.data, v)
 
for k,v in pairs(named) do
+
end
if type(v) == "function" then
 
newthing.data[k] = invokeInDefinition(v)
 
else
 
newthing.data[k] = v
 
end
 
end
 
 
for i,v in ipairs(positional) do
 
if type(v) == "function" then
 
for j,w in ipairs(invokeInDefinition(v)) do
 
newthing.data[#(newthing.data)+1] = w
 
end
 
 
else
 
else
newthing.data[#(newthing.data)+1] = v
+
if type(v) == "function" then
  +
newthing.data[k] = invokeInDefinition(v)
 
else
  +
newthing.data[k] = v
 
end
 
end
 
end
 
end
 
end
Line 340: Line 354:
   
 
local success = false
 
local success = false
local module = false, {}
+
local module = {}
 
local moduleName = "Module:Navbox/" .. frame.args[1]
 
local moduleName = "Module:Navbox/" .. frame.args[1]
 
if frame.args.forceUntranslated then
 
if frame.args.forceUntranslated then
Line 353: Line 367:
 
success, module = tryLoadModule(moduleName)
 
success, module = tryLoadModule(moduleName)
 
if not success then
 
if not success then
return out .. "<br/>!!! Could not load [[" .. moduleName .. "]] : " .. module .. " !!!"
+
return out .. "<br />!!! Could not load [[" .. moduleName .. "]] : " .. module .. " !!!"
 
end
 
end
 
end
 
end
Line 366: Line 380:
 
definitionEnvironment.line,
 
definitionEnvironment.line,
 
definitionEnvironment.ni,
 
definitionEnvironment.ni,
  +
definitionEnvironment.nid,
 
definitionEnvironment.l)
 
definitionEnvironment.l)
 
 
 
local context = {}
 
local context = {}
 
context.name = frame.args.name
 
context.name = frame.args.name
context.collapse = getParameter(frame, "collapse")
+
context.state = getParameter(frame, "state") or "autocollapse"
 
context.opengroups = {}
 
context.opengroups = {}
 
-- opengroups is a set, not a list.
 
-- opengroups is a set, not a list.

Latest revision as of 03:15, 24 August 2020

Exported functions

navbox

Emit a navbox. Has three named parameters:

Parameter Function
1 Mandatory Subpage of Module:Navbox to load the definition from.
name Mandatory Page to link to in the v.d.e bit of the navbox header.
fromParent If present, read the previous two parameters from the page that invoked the one the #invoke is on. ie, use this in your wrapper template
forceUntranslated Debugging only If present, load the untranslated version of the navbox, instead of a translation.

Navbox definitions

The module must have one member, navbox, which must be a function with the following signature:

function(navbox, highlightline, group, list, line, ni, nid, l)

The function returns a navbox definition built by calling the functions passed to it.

The top of the tree is a navbox{}
    title: Mandatory wikitext to display as the navbox's title
    Can contain a mix of group{}, list{}, and highlightline{}

group{} are the collapsible groups.
    title: Mandatory wikitext to title the group with.
    name: Untranslated name to refer to it in things like the opengroups template parameter.
    Can contain list{} and highlightline{}

list{}
    title: Optional title to display at the left.
    Can contain list{}/line{}, in which case the lists will be formatted tabley/subgroupy,
    or string/ni{}/l{}, which will be formatted as a hlist. Note that the *first*
    positional argument determines if it's a table or not.
    
highlightline{}
    Contents are concatenated (with space between) and displayed in a highlighted
    line like wp:Template:Navbox before= and after=
    
line{}
    Like list{} except it formats as a straight run of text rather than hlist. Can only contain
    string. ni{} or l{}

ni{}
    Invokes {{NI}} (or a facsimile, anyway)

nid{}
    Invokes {{NID}} (or a facsimile, anyway)
    
l{}
    Invokes the guts of {{L}}

text{}
    You should never need to use this directly. It's what strings are wrapped in.

--[[
All of the items in the definition tree for the navbox have an expand() method that
causes them to produce their markup:
expand(state, output)
where output is a function that adds its argument to the output, and state is state variables.
output's job also includes calling expand() on any tables!

The top of the tree is a navbox{}
    title: Mandatory wikitext to display as the navbox's title
    Can contain a mix of group{}, list{}, and highlightline{}

group{} are the collapsible groups.
    title: Mandatory wikitext to title the group with.
    name: Untranslated name to refer to it in things like the opengroups template parameter.
    Can contain list{} and highlightline{}

list{}
    title: Optional title to display at the left.
    Can contain list{}/line{}, in which case the lists will be formatted tabley/subgroupy,
    or string/ni{}/l{}, which will be formatted as a hlist. Note that the *first*
    positional argument determines if it's a table or not.
    
highlightline{}
    Contents are concatenated (with space between) and displayed in a highlighted
    line like wp:Template:Navbox before= and after=
    
line{}
    Like list{} except it formats as a straight run of text rather than hlist. Can only contain
    string. ni{} or l{}

ni{}
    Invokes {{NI}} (or a facsimile, anyway)

nid{}
    Invokes {{NID}} (or a facsimile, anyway)
    
l{}
    Invokes the guts of {{L}}

text{}
    You should never need to use this directly. It's what strings are wrapped in.

Strings will be presented literally in the output. Functions are allowed: in the positional
arguments to any of the above functions, any function will be evaluated in the same way as 
navbox{}, and then be replaced by the positional elements of the table it returns. Same deal
in the named arguments except the return is used directly. In the interests of non-silly
output, strings are joined with a space.

line{ "a", function() return { "1", "2" } end, "b" } is equivalent to,
line{ "a", "1", "2", "b" }

list{ title = function() return "foo" end, "1", "2" } is equivalent to,
list{ title = "foo", "1", "2" }

The exported function, navbox(), has three template parameters: {
    [1] = Name of the navbox definition to use
    name = template name for generating the v.d.e links
}
]]

local ipairs, pairs, rawget, type = ipairs, pairs, rawget, type

local util = require("Module:Utility_functions")
local language = require("Module:Language")

local element = {
    addDataToOutput = function(self, context, output, options)
        local oldmod = context.mod
        context.mod = self.data.mod or oldmod or "UNDEFINED"
        local oldmodname = context.modname
        context.modname = self.data.modname or oldmodname or "Undefined"
        for i, item in ipairs(self.data) do
            output((options.surround or {''})[1])
            self:expandItem(item, context, output, options.spacer)
            output((options.surround or {'',''})[2])
            if (i < #(self.data)) and options.separator then
                output(options.separator)
            end
        end
        context.mod = oldmod
    end,
    
    expandItem = function(self, item, context, output, spacer)
        if type(item) == "table" then
            item:expand(context, output)
        else
            output(tostring(item or ''))
        end
        output(spacer or '')
    end,
    
    expandOrMessage = function(self, item, context, output, spacer, message)
        if item then
            self:expandItem(item, context, output, spacer)
        else
            output(message)
        end
    end
}

-- The navbox as a whole.
element.navbox = {
    expand = function(self, context, output)
        output('<table class="navbox" cellspacing="0"><tr><td style="padding: 2px;">')
        output('<table class="nowraplinks')
        output(' mw-collapsible ')
        if context.state == "plain" or context.state == "off" then
            output('mw-collapsed')
        end
        output('" cellspacing="0" style="width:100%; background: transparent; color: inherit;"')
        output(' data-expandtext="show" data-collapsetext="hide">')
        output('<tr><th colspan="2" class="navbox-title"><span style="float:left;width:6em;text-align:left;">')
        output(mw.getCurrentFrame():expandTemplate{title="Navbar", args={mini="1", context.name}})
        output('</span><span style="font-size: 110%">')
        self:expandOrMessage(self.data.title, context, output, ' ', '!!! Missing title !!!')
        output('</span>')
        output('</th></tr>')
        output('<tr style="height: 2px;"><td></td></tr>')
        
        self:addDataToOutput(context, output, {separator = '<tr style="height: 2px;"><td></td></tr>'})
        
        output('</table>')
        output('</td></tr></table>')
    end
}

-- The collapsible groups that are the first division of the navbox.
element.group = {
    expand = function(self, context, output)
        context.odd = true
        
        output('<tr><td colspan="2" class="navbox-list" style="width:100%; padding:0px;">')
        output('<div style="padding:0em 0.25em"> </div>')
        output('<table class="nowraplinks mw-collapsible')
        -- These two semicolons stops something from wrapping tables in gratuitous divs
        output(' navbox-subgroup" cellspacing="0" style="width:100%;"')
        output(' data-expandtext="show" data-collapsetext="hide">')
        output('<tr><th class="navbox-title" colspan="2">')
        output('<span style="float:left;width:6em;">&nbsp;</span><span style="font-size: 100%;">')
        self:expandOrMessage(self.data.title, context, output, ' ', '!!! Missing title !!!')
        output('</span></th></tr>')
        output('<tr style="height: 2px;"><td></td></tr>')
        
        self:addDataToOutput(context, output, {spacer = '', separator='<tr style="height: 2px;"><td></td></tr>'})
        
        output('</table>')
        output('</td></tr>')
    end
}

-- A group-level thingy that displays text in a contrasting background.
element.highlightline = {
    expand = function(self, context, output)
        output('<tr><td colspan="2" class="navbox-abovebelow">')
        self:addDataToOutput(context, output, {spacer = ' '})
        output('</td></tr>')
    end
}

-- The remaining subdivisions of the navbox; with the title at the left, optionally.
element.list = {
    expand = function(self, context, output)
        if #(self.data) == 0 then
            return
        end

        local hasChildLists = (type(self.data[1]) == "table") and ((self.data[1].elementType == "list") or (self.data[1].elementType == "line"))
        
        output('<tr>')
        if self.data.title then
            output('<td class="navbox-group" style="padding-left: 0em; padding-right:0em;"><div style="padding:0em 0.75em;">')
            self:expandItem(self.data.title, context, output)
            output('</div></td>')
            output('<td style="text-align:left;border-left-width:2px;border-left-style:solid;width:100%;padding:0px;"')
        else
            output('<td colspan="2" style="')
            if hasChildLists then
                output('text-align:left;')
            end
            output('border-left-width:2px;border-left-style:solid;width:100%;padding:0px;"')
        end
        
        if context.odd then
            output(' class="navbox-list navbox-odd">')
        else
            output(' class="navbox-list navbox-even">')
        end
        
        
        if hasChildLists then
            output('<table class="nowraplinks navbox-subgroup" cellspacing="0" style="width: 100%;">')
            self:addDataToOutput(context, output, {separator = '<tr style="height: 2px;"><td></td></tr>'})
            output('</table>')
        else
            context.odd = not context.odd
            output('<ul class="hlist" style="padding:0em 0.25em; margin: 0;">')
            self:addDataToOutput(context, output, {surround = {' <li class="nowrap"> ',' </li> '}})
            output('</ul>')
        end
        
        output('</td></tr>')
    end
}

-- Like list, except it doesn't format as a list.
element.line = {
    expand = function(self, context, output)
        output('<tr>')
        if self.data.title then
            output('<th>' .. tostring(self.data.title) .. '</th>')
            output('<td>')
        else
            output('<td colspan="2">')
        end
        
        self:addDataToOutput(context, output, {spacer = ' '})
        
        output('</td></tr>')
    end
}

-- Invocation of {{NI}}, or at least the equivalent thereof.
element.ni = {
    expand = function(self, context, output)
        if self.data.icon then
            output("[[File:" .. self.data.icon .. "|16px|link=]]")
        else
            local iconargs = {
            	"",
                item = (self.data.gicon or self.data[1]),
                size=16,
                mod=(self.data.mod or context.mod)
            }
            output(mw.getCurrentFrame():callParserFunction("#icon", iconargs))
        end
        output("&nbsp;")
        local linkargs = { self.data[2] or self.data[1], (self.data[3] or self.data[2]) or mw.getCurrentFrame():callParserFunction("#iconloc", {self.data[1], self.data.mod or context.mod, "name", mw.title.getCurrentTitle().subpageText:lower()})}
        output(language.link(linkargs))
    end
}

-- Invocation of {{NID}}, or at least the equivalent thereof.
element.nid = {
    expand = function(self, context, output)
       if self.data.icon then
            output("[[File:" .. self.data.icon .. "|16px|link=]]")
        else
            local iconargs = {
            	"",
                item = (self.data.gicon or self.data[1]),
                size = 16,
                mod = (self.data.mod or context.mod)
            }
            output(mw.getCurrentFrame():callParserFunction("#icon", iconargs))
        end
        output("&nbsp;")
        local linkargs = { self.data[1] .. " (" .. context.modname .. ")", (self.data[2]) or mw.getCurrentFrame():callParserFunction("#iconloc", {self.data[1], self.data.mod or context.mod, "name", mw.title.getCurrentTitle().subpageText:lower()})}
        output(language.link(linkargs))
    end
}

-- Invocation of {{L}}, or an equivalent.
element.l = {
    expand = function(self, context, output)
        output(language.link(self.data))
    end
}

-- literal string
element.text = {
    expand = function(self, context, output)
        output(self.data)
    end
}

-- This environment is interposed in the one available to the function in definition.navbox.
local definitionEnvironment = {}

-- Note that this doesn't handle arguments!
--[[local function invokeInDefinition(func)
    local origEnv = getfenv(func)
    local newEnv = {}
    setmetatable(newenv, { __index = function(tab, key)
        return definitionEnvironment[key] or origEnv[key]
    end})
    setfenv(func, newEnv)
    local result = func()
    setfenv(func, origEnv)
    return result
end]]

-- stub because getfenv doesn't exist.
local function invokeInDefinition(func)
    return func()
end

local function createElement(name, metatable, args)
    local newthing = { elementType = name, data = {} }
    setmetatable(newthing, element[name])

    for k, v in pairs(args) do
        if type(k) == "number" then
	        if type(v) == "function" then
	            for j, w in ipairs(invokeInDefinition(v)) do
	                table.insert(newthing.data, w)
	            end
	        else
	            table.insert(newthing.data, v)
	        end
        else
	        if type(v) == "function" then
	            newthing.data[k] = invokeInDefinition(v)
	        else
	            newthing.data[k] = v
	        end
        end
    end

    return newthing
end

for name, metatable in pairs(element) do
    if type(metatable) == "table" then
        metatable.__index = function(tab, key)
            return (rawget(tab, key) or rawget(metatable, key)) or rawget(element, key)
        end
        definitionEnvironment[name] = function(args)
            return createElement(name, metatable, args)
        end
    end
end

local p = {}

local function tryLoadModule(name)
    return pcall(function()
        return require(name)
    end)
end

local function getParameter(frame, name)
    if frame.args.fromParent then
        return frame.args[name] or frame:getParent().args[name]
    else
        return frame.args[name]
    end
end

function p.navbox(frame)
    local out = ""
    local output = function(text)
        out = out .. tostring(text or '')
    end

    local success = false
    local module = {}
    local moduleName = "Module:Navbox/" .. frame.args[1]
    if frame.args.forceUntranslated then
        success, module = tryLoadModule(moduleName)
        if not success then
            return "!!! Could not load [[" .. moduleName .. "]] : " .. module .. " !!!"
        end
    else
        success, module = tryLoadModule(moduleName .. util.pageSuffix())
        if not success then
            output("!!! Could not load [[" .. moduleName  .. util.pageSuffix() .. "]], loading untranslated fallback. " .. module .. " !!!")
            success, module = tryLoadModule(moduleName)
            if not success then
                return out .. "<br />!!! Could not load [[" .. moduleName .. "]] : " .. module .. " !!!"
            end
        end
    end
    
    local navboxModule = module
    local navboxData = navboxModule.navbox(
        definitionEnvironment.navbox,
        definitionEnvironment.highlightline,
        definitionEnvironment.group,
        definitionEnvironment.list,
        definitionEnvironment.line,
        definitionEnvironment.ni,
        definitionEnvironment.nid,
        definitionEnvironment.l)
    
    local context = {}
    context.name = frame.args.name
    context.state = getParameter(frame, "state") or "autocollapse"
    context.opengroups = {}
    -- opengroups is a set, not a list.
    for str in string.gmatch(getParameter(frame, "opengroups") or '', "%S+") do
        context.opengroups[str] = true
    end

    output('<div style="display:none">')
    output(util.table_print(frame.args))
    output('</div>')
    
    navboxData:expand(context, output)
    return out
end

return p