Module:Navbox: Difference between revisions

From Workers & Resources: Soviet Republic Official Wiki
workers-resources-fandom>Abominação
(Created page with "-- ==================== -- This module exist to add some extra functionalities for navboxes -- Credits: This module was taken from Nukapedia -- ==================== local p = {} local collapseOptions = { ["collapsed"] = "mw-collapsible mw-collapsed", ["collapsedgroups"] = "mw-collapsible mw-collapsed", ["uncollapsed"] = "mw-collapsible", ["uncollapsedgroups"] = "mw-collapsible", } function p.collapse(frame) local optionGroups = mw...")
 
workers-resources-fandom>Abominação
No edit summary
Line 1: Line 1:
-- ====================
-- ====================
-- This module exist to add some extra functionalities for navboxes
-- This Module is used for making templates based in the Lua language.
-- Credits: This module was taken from Nukapedia
-- See more details about Lua in [[Help:Lua]].
-- ====================
-- The Fandom Developer's Wiki hosts Global Lua Modules that can be imported and locally overridden.
-- The next line imports the Navbox module from the [[w:c:dev:Global Lua Modules]].
 
-- Taken From Dev wiki to allow for custom params (with small modifications)
--------------------------------------------------------------------
--<pre> Navbox Module
--
-- * Fully CSS styled (inline styles possible but not default)
-- * Supports unlimited rows
--
-- By User:Tjcool007 from layton.fandom.com
--------------------------------------------------------------------


local p = {}
local p = {}


local collapseOptions = {
local args = {} -- Arguments passed to template
     ["collapsed"]         = "mw-collapsible mw-collapsed",
local navbox -- Actual navbox
    ["collapsedgroups"]   = "mw-collapsible mw-collapsed",
 
    ["uncollapsed"]       = "mw-collapsible",
--local working = {}
    ["uncollapsedgroups"] = "mw-collapsible",  
local rownums, skiprows = {}, {}
}
local hasrows, alt, hasData, isChild = false, false, false, false
local activeSection, sections, cimage, cimageleft
local colspan, rowspan
 
local showText, hideText = 'Show', 'Hide'
 
local langCode = mw.getContentLanguage():getCode()
local localization = {} --localized strings table
localization['en'] = {show = 'Show', hide = 'Hide'}
localization['ru'] = {show = 'показать', hide = 'скрыть'}
localization['zh'] = {show = '显示', hide = '隐藏'}
if localization[langCode] then
     showText = localization[langCode]['show']
    hideText = localization[langCode]['hide']
end
 
------------------------------------------------
-- Title
------------------------------------------------
 
--- Processes the VDE links in the title
--
-- @param titlecell The table cell of the title
local function processVde( titlecell )
if not args.template then return end
 
titlecell:wikitext('<span class="navbox-vde">'
.. mw.getCurrentFrame():expandTemplate({
title = 'vdelinks',
args = { args.template, ['type'] = 'navbox' }
}) .. '</span>')
end
 
--- Processes the main title row
local function processTitle()
local titlerow = mw.html.create('tr'):addClass('navbox-title')
local titlecell = mw.html.create('th'):attr('colspan',colspan):attr('scope','col')
 
if not pcall( processVde, titlecell ) then
titlecell:wikitext( '<b class="navbox-vde error" title="Missing Template:Vdelinks">!!!</b>' )
end
 
titlecell:wikitext( args.title or '{{{title}}}' )
 
-- Padding
local hasTemplate = args.template ~= nil
local hasState = not args.state or args.state ~= 'plain'
 
if hasTemplate ~= hasState then
if hasTemplate then
titlecell:addClass('navbox-title-padright')
else
titlecell:addClass('navbox-title-padleft')
end
end
 
if args.titleclass then titlerow:addClass( args.titleclass ) end
if args.titlestyle then titlecell:cssText( args.titlestyle ) end
 
titlerow:node(titlecell)
navbox:node(titlerow)
end
 
local function _addGutter( parent, incRowspan )
parent:tag('tr'):addClass('navbox-gutter'):tag('td'):attr('colspan',2)
 
if incRowspan then
rowspan = rowspan + 1
end
end
 
------------------------------------------------
-- Above/Below
------------------------------------------------
 
--- Processes the above and below rows
--
-- @param rowtype Either 'above' or 'below'
local function processAboveBelow( rowtype )
if not args[rowtype] then return end
 
local abrow = mw.html.create('tr'):addClass('navbox-'..rowtype)
local abcell = mw.html.create('td'):attr('colspan',colspan):wikitext( args[rowtype] )
 
if args[rowtype .. 'class'] then abrow:addClass( args[rowtype .. 'class'] ) end
if args[rowtype .. 'style'] then abcell:cssText( args[rowtype .. 'style'] ) end
 
abrow:node( abcell )
_addGutter( navbox )
navbox:node( abrow )
end
 
------------------------------------------------
-- Main Rows
------------------------------------------------
 
--- Processes the images
local function _processImage(row, imgtype)
if not args[imgtype] then return end
 
local iclass = imgtype == 'image' and 'navbox-image-right' or 'navbox-image-left'
 
local imagecell = mw.html.create('td'):addClass('navbox-image'):addClass(iclass)
 
local image = args[imgtype]
if image:sub(1,1) ~= '[' then
local width = args[imgtype .. 'width'] or '100px'
imagecell:css('width',width):wikitext('['..'[' .. image  .. '|' .. width .. '|link=' .. (args[imgtype .. 'link'] or '') .. ']]')
else
imagecell:css('width','0%'):wikitext(image)
end
 
if args[imgtype .. 'class'] then imagecell:addClass( args[imgtype .. 'class'] ) end
if args[imgtype .. 'style'] then imagecell:cssText( args[imgtype .. 'style'] ) end
 
row:node( imagecell )
if imgtype == 'image' then
cimage = imagecell
else
cimageleft = imagecell
end
end
 
--- Closes the currently active section (if any)
local function _closeCurrentSection()
if not activeSection then return end
 
local row = mw.html.create('tr'):addClass('navbox-section-row')
local cell = mw.html.create('td'):attr('colspan',2)
 
if not hasrows then
_processImage(row,'imageleft')
end
 
cell:node(sections[activeSection])
row:node(cell)
 
local firstRow = false
if not hasrows then
firstRow = true
hasrows = true
_processImage(row,'image')
end
 
_addGutter(navbox,not firstRow)
navbox:node(row)
rowspan = rowspan + 1
 
activeSection = false
hasData = false
end
 
--- Handles alternating rows
--
-- @return Alternatingly returns true or false. Always returns false if alternating rows
--        are disabled with "alternaterows = no"
local function _alternateRow()
if args.alternaterows == 'no' then return false end
if alt then
alt = false
return true
else
alt = true
return false
end
end
 
--- Process a single Header "row"
--
-- @param num Number of the row to be processed
local function processHeader(num)
if not args['header'..num] then return end
 
_closeCurrentSection()
 
local subtable = mw.html.create('table'):addClass('navbox-section')
local headerrow = mw.html.create('tr')
local header = mw.html.create('th'):addClass('navbox-header'):attr('colspan',2):attr('scope','col'):wikitext( args['header'..num] )
 
local collapseme = args['state'..num] or false
local state = false
 
if collapseme then
-- Look at this one
if collapseme ~= 'plain' then
state = collapseme == 'expanded' and 'expanded' or 'collapsed'
end
else
-- Look at default
local collapseall = args.defaultstate or false
if collapseall then
state = collapseall == 'expanded' and 'expanded' or 'collapsed'
end
end
 
if state then
subtable:addClass('mw-collapsible'):attr('data-expandtext',args['expandtext'..num] or args['defaultexpandtext'] or showText):attr('data-collapsetext',args['collapsetext'..num] or args['defaultcollapsetext'] or hideText)
if state == 'collapsed' then
subtable:addClass('mw-collapsed')
end
header:addClass('navbox-header-collapsible')
end
 
if args.headerclass then headerrow:addClass( args.headerclass ) end
if args.headerstyle then header:cssText( args.headerstyle ) end
 
headerrow:node(header)
subtable:node(headerrow)
 
sections[num] = subtable
activeSection = num
end
 
--- Processes a single list row
--
-- @param num Number of the row to be processed
local function processList(num)
if not args['list'..num] then return end
 
local row = mw.html.create('tr'):addClass('navbox-row')
 
if not hasrows and not activeSection then
_processImage(row, 'imageleft')
end
 
local listcell = mw.html.create('td'):addClass('navbox-list')
local hlistcell = listcell:tag('div'):addClass('hlist')
local data = args['list'..num]
if data:sub(1,1) == '*' then
-- Add newlines to support lists properly
hlistcell
:newline()
:wikitext( data )
:newline()
else
hlistcell:wikitext( data )
end
 
local altRow = _alternateRow()
if altRow then
row:addClass( args.altrowclass or 'alt' )
 
local listclass = args.altlistclass or args.listclass or false
if listclass then listcell:addClass( listclass ) end
 
local liststyle = args.altliststyle or args.liststyle or false
if liststyle then listcell:cssText( liststyle ) end
else
if args.rowclass then row:addClass( args.rowclass ) end
if args.listclass then listcell:addClass( args.listclass ) end
if args.liststyle then listcell:cssText( args.liststyle ) end
end
 
if args['group'..num] then
local groupcell = mw.html.create('th'):addClass('navbox-group'):attr('scope','row'):wikitext( args['group'..num] )
 
if altRow then
local groupclass = args.altgroupclass or args.groupclass or false
if groupclass then groupcell:addClass( groupclass ) end
local groupstyle = args.altgroupstyle or args.groupstyle or false
if groupstyle then groupcell:cssText( groupstyle ) end
else
if args.groupclass then groupcell:addClass( args.groupclass ) end
if args.groupstyle then groupcell:cssText( args.groupstyle ) end
end
 
row:node( groupcell )
else
listcell:attr('colspan',2):addClass('no-group')
end
 
row:node( listcell )
 
local firstRow = false
if not hasrows and not activeSection then
firstRow = true
hasrows = true
_processImage(row, 'image')
end
 
if activeSection then
local parent = sections[activeSection]
if not isChild or not firstRow then
_addGutter(parent)
end
parent:node(row)
hasData = true
else
if not isChild or not firstRow then
_addGutter(navbox,not firstRow)
end
navbox:node( row )
rowspan = rowspan + 1
end
end
 
--- Processes all rows
local function processRows()
sections = {}
for i=1,#rownums do
local num = rownums[i]
if not skiprows[num] then
processHeader(num)
processList(num)
end
end
_closeCurrentSection()
if cimageleft then
cimageleft:attr('rowspan',rowspan)
end
if cimage then
cimage:attr('rowspan',rowspan)
end
end
 
------------------------------------------------
-- ARGUMENTS PREPROCESSOR
-- * Extracts arguments from frame and stores them in args table
-- * At the same time, checks for valid row numbers
------------------------------------------------
 
--- Preprocessor for the arguments.
-- Will fill up the args table with the parameters from the frame grouped by their type.
--
-- @param frame The frame passed to the Module.
local function preProcessArgs(frame)
local tmp = {}
 
if frame == mw.getCurrentFrame() then
tmp = frame:getParent().args
else
tmp = frame
end
 
-- Storage tables
local nums = {}
 
-- Loop over all the args
for k,v in pairs(tmp) do
-- Skip empty args, which are useless
if v ~= '' then
local cat,num = tostring(k):match('^(%a+)([1-9]%d*)$')
 
if cat == 'header' or cat == 'list' then
nums[num] = true
end
 
args[k] = v -- Simple copy
end
end
 
colspan = args.image and 3 or 2
if args.imageleft then colspan = colspan + 1 end
rowspan = 0
 
if args.alternaterows == 'swap' then
alt = true
end
 
for k, v in pairs(nums) do
rownums[#rownums+1] = tonumber(k)
end
 
table.sort(rownums)


function p.collapse(frame)
-- Calculate skip rows
    local optionGroups = mw.text.split(frame.args[1], ",")
local cSection, cSkip
    local optionCount = table.getn(optionGroups)
local showall = args.showall
    if optionCount > 0 then
for i=1,#rownums do
        n = 1
local num = rownums[i]
        while n <= optionCount do
if args['header'..num] then
            if collapseOptions[optionGroups[n]] ~= nil then
cSection = true
                result = collapseOptions[optionGroups[n]]
cSkip = false
            end
local showme = args['show'..num]
            n = n + 1
if showme == 'no' then
        end
cSkip = true
    end
elseif showme == 'auto' or (showme ~= 'yes' and showall ~= 'yes') then
   
if not args['list'..num] then
    if result == nil then
local nextNum = rownums[i+1]
        result = "mw-collapsible mw-collapsed"
cSkip = not nextNum or args['header'..nextNum] -- If next has a header -> skip
    end
end
   
end
    return result
end
if cSection and cSkip then
skiprows[num] = true
end
end
end
end


function p.toggle(frame)
------------------------------------------------
    local toggleGroups = mw.text.split(frame.args[1], ",")
-- MAIN FUNCTIONS
    local toggleCount = table.getn(toggleGroups)
------------------------------------------------
    local toggleResult = 0
 
    if toggleCount > 0 then
--- Processes the arguments to create the navbox.
        n = 1
--
        while n <= toggleCount do
-- @return A string with HTML that is the navbox.
            if collapseOptions[toggleGroups[n]] ~= nil then
local function _navbox()
                toggleResult = toggleResult +1
-- Create the root HTML element
            end
local trim = function(s)
            n = n + 1
return s and mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1") or ''
        end
end
    end
local border = args.border or trim(args[1]) or ''
   
isChild = (border == 'child' or border == 'subgroup')
    if toggleResult > 0 then
 
        result = '<td class="np-navbox-header-side mw-customtoggle-myDivision" data-expandtext="Show" data-collapsetext="Hide"></td>'
if isChild then
    else
navbox = mw.html.create('table'):addClass('navbox-subgroup')
        result = '<td class="np-navbox-header-side>&nbsp;</td>'
else
    end
navbox = mw.html.create('table'):addClass('navbox')
   
 
    return result
if args.state ~= 'plain' then
navbox:addClass('mw-collapsible'):attr('data-expandtext',args['expandtext'] or args['defaultexpandtext'] or showText):attr('data-collapsetext',args['collapsetext'] or args['defaultcollapsetext'] or hideText)
if args.state == 'collapsed' then
navbox:addClass('mw-collapsed')
end
end
end
 
if args.bodyclass then navbox:addClass(args.bodyclass) end
if args.bodystyle then navbox:cssText(args.bodystyle) end
 
-- Process...
if not isChild then
processTitle()
processAboveBelow('above')
processRows()
processAboveBelow('below')
 
return tostring(navbox)
else
processRows()
 
local wrapper = mw.html.create('')
wrapper:wikitext('</div>')
wrapper:node(navbox)
wrapper:wikitext('<div class="hlist">')
return tostring(wrapper)
end
end
end


function p.columns(frame)
--- Main module entry point.
    local columnGroups = mw.text.split(frame.args[1], ",")
-- To be called with {{#invoke:navbox|main}} or directly from another module.
    local groupCount = table.getn(columnGroups)
--
    local columnResult = 0
-- @param frame The frame passed to the module via the #invoke. If called from another
   
--              module directly, this should be a table with the parameter definition.
    if groupCount > 0 then
function p.main(frame)
        n = 1
-- Save the arguments in a local variable so other functions can use them.
        while n <= table do
preProcessArgs(frame)
            if columnGroups[n] == "columns" then
                groupCount = groupCount + 1
return _navbox()
            end
        end
    end
   
    if columnResult > 0 then
        columnResult = "columns"
    end
   
    return columnResult
end
end


return p
return p

Revision as of 04:02, 10 January 2023

Lua error: callParserFunction: function "#translation" was not found.

See Template:Navbox


-- ====================
-- This Module is used for making templates based in the Lua language.
-- See more details about Lua in [[Help:Lua]].
-- The Fandom Developer's Wiki hosts Global Lua Modules that can be imported and locally overridden.
-- The next line imports the Navbox module from the [[w:c:dev:Global Lua Modules]].

-- Taken From Dev wiki to allow for custom params (with small modifications)
--------------------------------------------------------------------
--<pre> Navbox Module
--
-- * Fully CSS styled (inline styles possible but not default)
-- * Supports unlimited rows
--
-- By User:Tjcool007 from layton.fandom.com
--------------------------------------------------------------------

local p = {}

local args = {} -- Arguments passed to template
local navbox -- Actual navbox

--local working = {}
local rownums, skiprows = {}, {}
local hasrows, alt, hasData, isChild = false, false, false, false
local activeSection, sections, cimage, cimageleft
local colspan, rowspan

local showText, hideText = 'Show', 'Hide'

local langCode = mw.getContentLanguage():getCode()
local localization = {} --localized strings table
localization['en'] = {show = 'Show', hide = 'Hide'}
localization['ru'] = {show = 'показать', hide = 'скрыть'}
localization['zh'] = {show = '显示', hide = '隐藏'}
if localization[langCode] then
    showText = localization[langCode]['show']
    hideText = localization[langCode]['hide']
end

------------------------------------------------
-- Title
------------------------------------------------

--- Processes the VDE links in the title
--
-- @param titlecell The table cell of the title
local function processVde( titlecell )
	if not args.template then return end

	titlecell:wikitext('<span class="navbox-vde">'
		.. mw.getCurrentFrame():expandTemplate({
			title = 'vdelinks',
			args = { args.template, ['type'] = 'navbox' }
		}) .. '</span>')
end

--- Processes the main title row
local function processTitle()
	local titlerow = mw.html.create('tr'):addClass('navbox-title')
	local titlecell = mw.html.create('th'):attr('colspan',colspan):attr('scope','col')

	if not pcall( processVde, titlecell ) then
		titlecell:wikitext( '<b class="navbox-vde error" title="Missing Template:Vdelinks">!!!</b>' )
	end

	titlecell:wikitext( args.title or '{{{title}}}' )

	-- Padding
	local hasTemplate = args.template ~= nil
	local hasState = not args.state or args.state ~= 'plain'

	if hasTemplate ~= hasState then
		if hasTemplate then
			titlecell:addClass('navbox-title-padright')
		else
			titlecell:addClass('navbox-title-padleft')
		end
	end

	if args.titleclass then titlerow:addClass( args.titleclass ) end
	if args.titlestyle then titlecell:cssText( args.titlestyle ) end

	titlerow:node(titlecell)
	navbox:node(titlerow)
end

local function _addGutter( parent, incRowspan )
	parent:tag('tr'):addClass('navbox-gutter'):tag('td'):attr('colspan',2)

	if incRowspan then
		rowspan = rowspan + 1
	end
end

------------------------------------------------
-- Above/Below
------------------------------------------------

--- Processes the above and below rows
--
-- @param rowtype Either 'above' or 'below'
local function processAboveBelow( rowtype )
	if not args[rowtype] then return end

	local abrow = mw.html.create('tr'):addClass('navbox-'..rowtype)
	local abcell = mw.html.create('td'):attr('colspan',colspan):wikitext( args[rowtype] )

	if args[rowtype .. 'class'] then abrow:addClass( args[rowtype .. 'class'] ) end
	if args[rowtype .. 'style'] then abcell:cssText( args[rowtype .. 'style'] ) end

	abrow:node( abcell )
	_addGutter( navbox )
	navbox:node( abrow )
end

------------------------------------------------
-- Main Rows
------------------------------------------------

--- Processes the images
local function _processImage(row, imgtype)
	if not args[imgtype] then return end

	local iclass = imgtype == 'image' and 'navbox-image-right' or 'navbox-image-left'

	local imagecell = mw.html.create('td'):addClass('navbox-image'):addClass(iclass)

	local image = args[imgtype]
	if image:sub(1,1) ~= '[' then
		local width = args[imgtype .. 'width'] or '100px'
		imagecell:css('width',width):wikitext('['..'[' .. image  .. '|' .. width .. '|link=' .. (args[imgtype .. 'link'] or '') .. ']]')
	else
		imagecell:css('width','0%'):wikitext(image)
	end

	if args[imgtype .. 'class'] then imagecell:addClass( args[imgtype .. 'class'] ) end
	if args[imgtype .. 'style'] then imagecell:cssText( args[imgtype .. 'style'] ) end

	row:node( imagecell )
	if imgtype == 'image' then
		cimage = imagecell
	else
		cimageleft = imagecell
	end
end

--- Closes the currently active section (if any)
local function _closeCurrentSection()
	if not activeSection then return end

	local row = mw.html.create('tr'):addClass('navbox-section-row')
	local cell = mw.html.create('td'):attr('colspan',2)

	if not hasrows then
		_processImage(row,'imageleft')	
	end

	cell:node(sections[activeSection])
	row:node(cell)

	local firstRow = false
	if not hasrows then
		firstRow = true
		hasrows = true
		_processImage(row,'image')	
	end

	_addGutter(navbox,not firstRow)
	navbox:node(row)	
	rowspan = rowspan + 1

	activeSection = false
	hasData = false
end

--- Handles alternating rows
--
-- @return Alternatingly returns true or false. Always returns false if alternating rows
--         are disabled with "alternaterows = no"
local function _alternateRow()
	if args.alternaterows == 'no' then return false end
	if alt then
		alt = false
		return true
	else
		alt = true
		return false
	end
end

--- Process a single Header "row"
--
-- @param num Number of the row to be processed
local function processHeader(num)
	if not args['header'..num] then return end

	_closeCurrentSection()

	local subtable = mw.html.create('table'):addClass('navbox-section')
	local headerrow = mw.html.create('tr')
	local header = mw.html.create('th'):addClass('navbox-header'):attr('colspan',2):attr('scope','col'):wikitext( args['header'..num] )

	local collapseme = args['state'..num] or false
	local state = false

	if collapseme then
		-- Look at this one
		if collapseme ~= 'plain' then
			state = collapseme == 'expanded' and 'expanded' or 'collapsed'
		end
	else
		-- Look at default 
		local collapseall = args.defaultstate or false
		if collapseall then
			state = collapseall == 'expanded' and 'expanded' or 'collapsed'	
		end
	end

	if state then
		subtable:addClass('mw-collapsible'):attr('data-expandtext',args['expandtext'..num] or args['defaultexpandtext'] or showText):attr('data-collapsetext',args['collapsetext'..num] or args['defaultcollapsetext'] or hideText)
		if state == 'collapsed' then
			subtable:addClass('mw-collapsed')	
		end
		header:addClass('navbox-header-collapsible')
	end

	if args.headerclass then headerrow:addClass( args.headerclass ) end
	if args.headerstyle then header:cssText( args.headerstyle ) end

	headerrow:node(header)	
	subtable:node(headerrow)

	sections[num] = subtable
	activeSection = num
end

--- Processes a single list row
--
-- @param num Number of the row to be processed
local function processList(num)	
	if not args['list'..num] then return end

	local row = mw.html.create('tr'):addClass('navbox-row')

	if not hasrows and not activeSection then
		_processImage(row, 'imageleft')	
	end

	local listcell = mw.html.create('td'):addClass('navbox-list')
	local hlistcell = listcell:tag('div'):addClass('hlist')
	
	local data = args['list'..num]
	
	if data:sub(1,1) == '*' then
		-- Add newlines to support lists properly
		hlistcell
			:newline()
			:wikitext( data )
			:newline()
	else
		hlistcell:wikitext( data )
	end

	local altRow = _alternateRow()
	if altRow then
		row:addClass( args.altrowclass or 'alt' )

		local listclass = args.altlistclass or args.listclass or false
		if listclass then listcell:addClass( listclass ) end

		local liststyle = args.altliststyle or args.liststyle or false
		if liststyle then listcell:cssText( liststyle ) end
	else
		if args.rowclass then row:addClass( args.rowclass ) end
		if args.listclass then listcell:addClass( args.listclass ) end
		if args.liststyle then listcell:cssText( args.liststyle ) end
	end

	if args['group'..num] then
		local groupcell = mw.html.create('th'):addClass('navbox-group'):attr('scope','row'):wikitext( args['group'..num] )

		if altRow then
			local groupclass = args.altgroupclass or args.groupclass or false
			if groupclass then groupcell:addClass( groupclass ) end
 
			local groupstyle = args.altgroupstyle or args.groupstyle or false
			if groupstyle then groupcell:cssText( groupstyle ) end
		else	
			if args.groupclass then groupcell:addClass( args.groupclass ) end
			if args.groupstyle then groupcell:cssText( args.groupstyle ) end
		end

		row:node( groupcell )
	else
		listcell:attr('colspan',2):addClass('no-group')
	end

	row:node( listcell )

	local firstRow = false
	if not hasrows and not activeSection then
		firstRow = true
		hasrows = true
		_processImage(row, 'image')
	end

	if activeSection then
		local parent = sections[activeSection]
		if not isChild or not firstRow then
			_addGutter(parent)
		end
		parent:node(row)
		hasData = true
	else
		if not isChild or not firstRow then
			_addGutter(navbox,not firstRow)
		end
		navbox:node( row )
		rowspan = rowspan + 1
	end
end

--- Processes all rows
local function processRows()
	sections = {}
	for i=1,#rownums do
		local num = rownums[i]
		if not skiprows[num] then
			processHeader(num)
			processList(num)
		end
	end
	_closeCurrentSection()
 
	if cimageleft then
		cimageleft:attr('rowspan',rowspan)		
	end
	if cimage then
		cimage:attr('rowspan',rowspan)
	end
end

------------------------------------------------
-- ARGUMENTS PREPROCESSOR
-- * Extracts arguments from frame and stores them in args table
-- * At the same time, checks for valid row numbers
------------------------------------------------

--- Preprocessor for the arguments.
-- Will fill up the args table with the parameters from the frame grouped by their type.
--
-- @param frame The frame passed to the Module.
local function preProcessArgs(frame)
	local tmp = {}

	if frame == mw.getCurrentFrame() then
		tmp = frame:getParent().args
	else
		tmp = frame
	end

	-- Storage tables
	local nums = {}

	-- Loop over all the args
	for k,v in pairs(tmp) do
		-- Skip empty args, which are useless
		if v ~= '' then
			local cat,num = tostring(k):match('^(%a+)([1-9]%d*)$')

			if cat == 'header' or cat == 'list' then
				nums[num] = true
			end

			args[k] = v -- Simple copy
		end
	end

	colspan = args.image and 3 or 2
	if args.imageleft then colspan = colspan + 1 end
	rowspan = 0

	if args.alternaterows == 'swap' then
		alt = true
	end

	for k, v in pairs(nums) do
		rownums[#rownums+1] = tonumber(k)
	end

	table.sort(rownums)

	-- Calculate skip rows
	local cSection, cSkip
	local showall = args.showall
	for i=1,#rownums do
		local num = rownums[i]
		if args['header'..num] then
			cSection = true
			cSkip = false
			local showme = args['show'..num]
			if showme == 'no' then
				cSkip = true
			elseif showme == 'auto' or (showme ~= 'yes' and showall ~= 'yes') then
				if not args['list'..num] then
					local nextNum = rownums[i+1]
					cSkip = not nextNum or args['header'..nextNum] -- If next has a header -> skip
				end
			end
		end
		if cSection and cSkip then
			skiprows[num] = true
		end
	end
end

------------------------------------------------
-- MAIN FUNCTIONS
------------------------------------------------

--- Processes the arguments to create the navbox.
--
-- @return A string with HTML that is the navbox.
local function _navbox()
	-- Create the root HTML element
	local trim = function(s)
		return s and mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1") or ''
	end
	local border = args.border or trim(args[1])  or ''
	isChild = (border == 'child' or border == 'subgroup')

	if isChild then
		navbox = mw.html.create('table'):addClass('navbox-subgroup')
	else
		navbox = mw.html.create('table'):addClass('navbox')

		if args.state ~= 'plain' then
			navbox:addClass('mw-collapsible'):attr('data-expandtext',args['expandtext'] or args['defaultexpandtext'] or showText):attr('data-collapsetext',args['collapsetext'] or args['defaultcollapsetext'] or hideText)
			if args.state == 'collapsed' then
				navbox:addClass('mw-collapsed')
			end
		end
	end

 	if args.bodyclass then navbox:addClass(args.bodyclass) end
	if args.bodystyle then navbox:cssText(args.bodystyle) end

	-- Process...
	if not isChild then
		processTitle()
		processAboveBelow('above')
		processRows()
		processAboveBelow('below')

		return tostring(navbox)
	else
		processRows()

		local wrapper = mw.html.create('')
		wrapper:wikitext('</div>')
		wrapper:node(navbox)
		wrapper:wikitext('<div class="hlist">')
		return tostring(wrapper)
	end
end

--- Main module entry point.
-- To be called with {{#invoke:navbox|main}} or directly from another module.
--
-- @param frame The frame passed to the module via the #invoke. If called from another
--              module directly, this should be a table with the parameter definition.
function p.main(frame)
	-- Save the arguments in a local variable so other functions can use them.
	preProcessArgs(frame)
 
	return _navbox()
end

return p